JVM Source Lens

Resolve o classpath real do seu projeto Gradle e retorna código-fonte Java, assinaturas de métodos e estrutura de classes para qualquer classe de dependência — usando a versão que sua build realmente utiliza, não arquivos aleatórios de ~/.gradle/caches.

Documentação

jvmsrc — Dê ao seu agente de codificação um IDE Java

CI npm version License: MIT Node

Um servidor MCP e CLI que dá ao seu agente de codificação a única coisa que falta em projetos JVM: o classpath real.


O Problema

Você usa um IDE para escrever Java. Seu agente de codificação não tem um.

Quando seu agente encontra um tipo de biblioteca desconhecido — digamos, uma superclasse de uma biblioteca interna proprietária — ele gasta mais de 25 turnos percorrendo ~/.gradle/caches, abrindo JARs manualmente com jar tf, escolhendo um por tentativa e erro, e tentando responder a uma pergunta que seu IDE responderia com um único toque de tecla: essa superclasse tem um método utilitário público chamado X?

A Solução

jvmsrc consulta sua ferramenta de build (Gradle) pelo classpath resolvido deste projeto e então entrega ao seu agente código-fonte real, assinaturas reais e estrutura real — para a versão exata que seu build realmente usa.

  • Como servidor MCP – Conecte-se ao Claude Code, Cursor, Windsurf ou qualquer outro host MCP e equipe seu agente com seis ferramentas de classpath feitas sob medida.
  • Como CLI jvmsrc – Mesmo motor, scriptável, compatível com pipes e útil por conta própria quando você só quer ler uma classe.

jvmsrc resolving a Spring class in Claude Code
Claude Code resolvendo assinaturas de HandlerInterceptor via jvmsrc — 3 chamadas, resposta correta, sem percorrer cache.


O que economiza, diariamente

Em projetos JVM com bibliotecas privadas e sem Javadocs públicos, jvmsrc é um multiplicador de força:

  • ~50 mil tokens economizados por investigação de "o que há nessa classe externa" — aproximadamente 70% de redução de custo.
  • Mais de 15 loops de pânico do agente evitados por dia — sem vasculhar caches do Gradle, abrir JARs errados ou desistir.
  • Desbloqueie delegação para tarefas complexas que envolvem SDKs internos que antes você precisava fazer sozinho.

A Diferença em Ação

Sem jvmsrc (A busca cega de 25 turnos)

Usuário: Sobrescreva o hook de auditoria de AbstractTradingService — existe um método utilitário público nele que devemos reutilizar?

Agente:

  1. Procura no workspace por AbstractTradingService.java ➔ 0 hits
  2. Executa: find ~/.gradle -name "trading-core*"
  3. Encontra 4 versões: 2.1.0, 2.3.0, 2.4.1, 3.0.0-SNAPSHOT
  4. Adivinha: Escolhe trading-core-2.4.1.jar (o projeto na verdade usa 3.0.0-SNAPSHOT!)
  5. Executa: jar tf e javap -p no JAR errado
  6. [22 turnos depois] "Não vejo um método utilitário, você terá que implementar você mesmo."

Realidade: 3.0.0-SNAPSHOT adicionou maskSensitiveFields() como um helper protegido exatamente para este caso. O agente não alucinou — ele estava apenas cego.

Com jvmsrc (A resolução instantânea em 3 turnos)

Usuário: Sobrescreva o hook de auditoria de AbstractTradingService — existe um método utilitário público nele que devemos reutilizar?

Agente:

  1. search_classes("AbstractTradingService") ➔ Encontra o FQN e a biblioteca resolvida exata.
  2. get_class_structure(scope: "overview") ➔ Descobre maskSensitiveFields() em 3.0.0-SNAPSHOT.
  3. get_method_signature("maskSensitiveFields") ➔ Obtém assinatura precisa e genéricos.

Resultado: Escreve a sobrescrita corretamente na primeira tentativa. Sem percorrer cache, sem adivinhação, sem versão errada.


Como Funciona

  1. Consulta à Ferramenta de Build: jvmsrc consulta sua ferramenta de build ativa (ex.: Gradle) pela configuração exata do classpath resolvido.
  2. Cache Inteligente: Ele armazena em cache o classpath resolvido, rastreando mudanças nos arquivos de build para se manter atualizado.
  3. Ferramentas de IA de Precisão: Em vez de despejar código completo, ele expõe ferramentas precisas e de alta granularidade (assinaturas, estrutura, busca) para manter as janelas de contexto pequenas e o uso de tokens ultrabaixo.

Instalação e Início Rápido

1. Instale a CLI

npm install -g jvmsrc

Ou use diretamente via npx:

npx jvmsrc mcp

[!IMPORTANTE]
Requer Node ≥ 20 e Java no PATH (para o decompilador CFR + javap).

2. Adicione o servidor MCP

Cole isto na configuração do seu assistente de IA (Cursor, Claude Code, Windsurf, etc.) e reinicie o host:

{
  "mcpServers": {
    "jvmsrc": {
      "command": "jvmsrc",
      "args": ["mcp"]
    }
  }
}

Opcional: jvmsrc config (ou jvmsrc config --project /path/to/gradle-project) imprime um bloco pronto para colar, além de dicas de ambiente. A maioria dos usuários pode pular e copiar o trecho acima.


Referência do Servidor MCP

O servidor MCP roda via stdio usando jvmsrc mcp. A configuração padrão não precisa de variáveis de ambiente:

{
  "mcpServers": {
    "jvmsrc": {
      "command": "jvmsrc",
      "args": ["mcp"]
    }
  }
}

Credenciais de repositório privado (opcional)

Necessário apenas quando seu build Gradle exige variáveis de ambiente de credenciais para um repositório privado Maven/Artifactory/Nexus. Hosts MCP frequentemente não herdam seu shell interativo, então essas variáveis devem ser definidas no processo MCP do jvmsrc (e então reiniciar o servidor).

REPO_USER / REPO_PASS abaixo são apenas nomes de exemplo — não são exigidos pelo jvmsrc. Use os nomes de variáveis que os scripts Gradle do seu projeto documentarem:

{
  "mcpServers": {
    "jvmsrc": {
      "command": "jvmsrc",
      "args": ["mcp"],
      "env": {
        "REPO_USER": "your-username",
        "REPO_PASS": "your-password"
      }
    }
  }
}

Omita o bloco env completamente quando o projeto não precisar delas.

Ferramentas que seu agente recebe

FerramentaO que faz
search_classesEncontra uma classe por nome simples ou glob; retorna listas compactas de FQN + nome da lib
get_class_structureRecupera visão geral da classe (propósito + nomes de métodos) ou assinaturas declaradas
get_method_signatureBusca sobrecargas reais de um método, com nomes de parâmetros e genéricos
find_in_class_sourceRealiza buscas por regex ou substring dentro de uma classe resolvida
get_class_sourceRecupera corpos de métodos ou intervalos de linhas (usado como último recurso)
search_in_artifactBusca texto em todas as classes de um JAR de dependência resolvido
resolve_dependenciesAnalisa o grafo de dependências real que este projeto usa

[!DICA]
Toda resposta de fonte inclui sourceAvailable: true para fontes reais (Javadoc, nomes de parâmetros, genéricos), false para decompilação CFR (estrutura confiável, nomes podem ser sintéticos).

[!NOTA]
Multimódulo: omita modulePath e o jvmsrc escolhe automaticamente o módulo proprietário único; em caso de falha, ele lista modulePaths candidatos. Métodos: search_classes corresponde a nomes de métodos declarados quando o índice tem enriquecimento de fonte; para texto de corpo em um JAR conhecido, use search_in_artifact. get_class_source methodNames também percorre superclasses para nomes sem correspondência.


Comparação

FerramentaAbordagemLacuna
Indexadores de Cache / grep ~/.gradleEscaneiam caches globaisSem versão resolvida por projeto
Parsers Estáticos (ex.: parser build.gradle)Analisam apenas declaraçõesPerdem dependências transitivas, BOMs, versões dinâmicas
mcp-javadoc / CFR somente por caminhoUsuário fornece caminhos de JAR manualmenteSem resolução automática de build/classpath
Gradle MCP (Tooling API)Focado em tarefas/buildNão otimizado para busca de fonte FQN com classpath preciso
jvmsrcConsulta a ferramenta de build real e armazena em cacheFontes e assinaturas corretas por versão para agentes

Público-Alvo

Principalmente projetos Java + Spring Boot com Gradle. Outras linguagens JVM (Kotlin, Scala) e Android funcionam hoje na base do melhor esforço e estão no roadmap como alvos de primeira classe — veja ROADMAP.md.

Se você usa Maven ou Bazel, está planejado, mas ainda não disponível. Dê uma estrela no repositório ou abra uma issue e eu priorizarei de acordo.


Referência Detalhada

Requisitos e Compatibilidade

Runtime: Node.js ≥ 20, Java no PATH.

Tipos de projeto: bases de código JVM (Java, Kotlin, Scala, Groovy). jvmsrc chama a ferramenta de build, não seu editor.

Sistema de buildStatus
GradleSuportado — multimódulo incluído
Maven, BazelPlanejado (SPEC.md)

Aponte -p / projectRoot para a raiz do Gradle (settings.gradle(.kts) ou build.gradle(.kts) raiz). Usa ./gradlew quando presente, senão gradle em PATH. Árvores somente Maven recebem um erro explícito de não suportado.

Limitações Conhecidas

Software em estágio inicial; o caminho suportado é estreito:

ÁreaHoje
Ferramenta de buildSomente Gradle
IntegraçãoScript init Groovy (--init-script) — não é um plugin do Portal Gradle
ClasspathsJVM padrão + configurações jvm* do Kotlin MPP quando o Gradle as expõe
SaídaTexto .java em formato Java (JAR de fontes, src entre projetos ou CFR)

Builds compostos, layouts somente Android e configurações exóticas não são totalmente validados. Veja ROADMAP.md.

Segurança e Privacidade
  • Sem telemetria.
  • Somente local — caches e diagnósticos ficam no disco; nunca grava dentro da raiz do seu projeto.
  • Subprocessos apenas via argv (sem interpolação de shell) — veja SECURITY.md.
  • JVMSRC_ALLOWED_ROOTS opcional para restringir quais projetos o jvmsrc pode resolver.
Referência de Comandos CLI
jvmsrc com.example.MyClass -p /path/to/gradle-project          # shorthand for get
jvmsrc get com.example.MyClass -p /path/to/project -q > MyClass.java
jvmsrc resolve -p /path/to/project --force-refresh
jvmsrc config jdk-roots add /path/to/jdks                      # one-time JDK roots setup
jvmsrc doctor java -p /path/to/project                         # check JDK requirement + selection
jvmsrc diagnostics last                                         # latest failure message
jvmsrc mcp                                                     # run as MCP server

Flags úteis: -p / --project, --module (:core:api), --configuration, --include-test, --force-refresh, --verbose (somente stderr do Gradle), --method, --start-line / --end-line.

Fixture de repositório para testes: test/fixtures/gradle-smoke — jvmsrc get com.smoke.Core -p test/fixtures/gradle-smoke --module :core.

Solução de Problemas
  • Falhas de resolução: Execute jvmsrc diagnostics last (ou jvmsrc diagnostics last 5)
  • Raízes de instalação JDK personalizadas: Adicione uma vez com jvmsrc config jdk-roots add /path/to/jdks
  • Depuração de incompatibilidade JDK: Execute jvmsrc doctor java -p /path/to/project
  • Após atualizar o jvmsrc: Reinicie seu host MCP
  • Classpath desatualizado: Execute jvmsrc resolve --force-refresh
Variáveis de Ambiente
VariávelPropósito
JVMSRC_JAVA_HOMEForça o home do JDK para processos filhos Gradle/CFR
JVMSRC_CONFIG_DIRDiretório global de configuração do jvmsrc (absoluto)
JVMSRC_CACHE_ROOTRaiz do cache (absoluto)
JVMSRC_LOG_DIRLogs de diagnóstico (absoluto)
JVMSRC_ALLOWED_ROOTSPrefixos projectRoot permitidos
JVMSRC_MAX_SOURCE_OUTPUT_CHARSTamanho máximo do corpo da fonte (padrão 524288)
JVMSRC_GRADLE_TIMEOUT_MSTimeout do Gradle
JVMSRC_CFR_PATHJAR CFR personalizado

Os padrões seguem as convenções de env-paths por SO. Layout completo: SPEC.md §6.

Quando JVMSRC_JAVA_HOME não está definido, o jvmsrc descobre automaticamente JDKs locais em caminhos comuns como ~/.jdks (IntelliJ), ~/.gradle/jdks, SDKMan, jenv, asdf e diretórios de instalação do sistema específicos do SO, além das raízes JDK configuradas globalmente em jvmsrc config jdk-roots ....

Avaliações de Agentes de IA

Finalmente, um MCP Que Não Me Faz Decompilar JARs

"Esta ferramenta é uma revelação para quem está cansado de LLMs alucinando APIs Spring inexistentes. Ela realmente lê bytecode, fornecendo definições de classe precisas e buscas de fonte sem a adivinhação usual baseada em 'vibes'. A funcionalidade search_classes é incrivelmente precisa, e a implementação cuidadosa do fallback javap e dos controles granulares de escopo (overview/declared/effective) torna a navegação em JARs complexos indolor. É rápida, honesta quando não encontra uma classe e gerencia o cache perfeitamente. Item obrigatório para qualquer dev que luta contra o inferno das dependências — é como ter um engenheiro sênior que realmente gosta de ler documentação." — Claude (Revisor de IA)


Documentação do Projeto

DocumentoConteúdo
SPEC.mdSchemas, contratos, detalhes de CLI/MCP
CONTRIBUTING.mdBuild, testes, notas de PR
RELEASING.mdRamificações, semver, lançamentos npm
CHANGELOG.mdHistórico de versões
ROADMAP.mdStatus e trabalho planejado
SECURITY.mdRelato de vulnerabilidades

Compilando a partir do código-fonte

git clone https://github.com/Sintexer/jvm-source-lens.git
cd jvm-source-lens
bun install && bun run setup:cfr && bun run build
node dist/cli.js --version

Fluxo de trabalho completo para contribuidores: CONTRIBUTING.md.


Eu construí o jvmsrc porque continuava batendo na mesma parede: agentes ótimos em escrever Java, mas cegos para o classpath real. Se isso poupar você dos mesmos 25 turnos de idas e vindas que poupou para mim, é exatamente para isso que isto existe. Encontrou um bug, tem uma ideia, ou só quer dizer que ajudou? Abra uma issue ou um PR — eu leio tudo.

Licença

MIT — veja LICENSE.