关于 JVM Source Lens
JVM Source Lens 为使用 Gradle 的 Java 项目提供 MCP 服务和 CLI,可解析项目实际类路径,查询对应版本的类源码、签名与结构。
主要功能
- 01解析 Gradle 类路径
- 02搜索类与依赖
- 03检查类结构和签名
- 04获取源码与方法体
- 05搜索依赖制品
适用场景
- 01查询陌生依赖的 API
- 02确认项目实际使用的版本
- 03实现重写前检查库方法
MCP 相关
通过 stdio 向 MCP 客户端提供类路径查询、源码、签名和依赖搜索工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y jvmsrcJVMSRC_ALLOWED_ROOTSOptional comma-separated absolute paths; only these project roots are allowed.JVMSRC_CACHE_ROOTOptional absolute path for resolution and decompile caches (default: OS cache dir).JVMSRC_LOG_DIROptional absolute path for failure diagnostic logs.JVMSRC_MAX_SOURCE_OUTPUT_CHARSMax characters returned for full-file source (default 524288).JVMSRC_GRADLE_TIMEOUT_MSGradle resolution subprocess timeout in milliseconds.JVMSRC_CFR_PATHOptional path to a custom CFR JAR for decompilation.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
7收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| full | boolean | 否 | |
| endLine | integer | 否 | |
| className | string | 是 | |
| startLine | integer | 否 | |
| methodName | string | 否 | |
| modulePath | string | 否 | |
| includeTest | boolean | 否 | |
| methodNames | array | 否 | |
| projectRoot | string | 是 | |
| forceRefresh | boolean | 否 | |
| configuration | string | 否 |
详细介绍
jvmsrc — 为你的编码 Agent 配备 Java IDE
问题所在
你用 IDE 编写 Java。你的编码 Agent 却没有 IDE。
当 Agent 遇到不熟悉的库类型时——比如某个专有内部库中的超类——它会花费 25+ 轮遍历 ~/.gradle/caches、用 jar tf 手动打开 JAR、凭猜测挑选一个,然后试图回答一个 IDE 只需一次按键就能回答的问题:这个超类是否有一个名为 X 的公共实用方法?
解决方案
jvmsrc 会查询你的构建工具(Gradle),获取此项目解析后的类路径,然后为你的 Agent 提供真实源码、真实签名和真实结构——与你的构建实际使用的版本完全一致。
- 作为 MCP 服务 – 连接到 Claude Code、Cursor、Windsurf 或任何其他 MCP 宿主,为你的 Agent 配备六种专用类路径工具。
- 作为
jvmsrcCLI – 使用相同引擎,可编写脚本、便于管道传递;如果你只想阅读某个类,它本身也很实用。
Claude Code 通过 jvmsrc 解析 HandlerInterceptor 签名——调用 3 次,答案准确,无需遍历缓存。
每天节省的时间与精力
对于使用私有库且没有公开 Javadoc 的 JVM 项目,jvmsrc 能大幅提升效率:
- 每次调查“这个外部类里有什么”时可节省 约 50K 个 token——成本约降低 70%。
- 每天避免 15+ 次 Agent 陷入慌乱的循环——不必再费力翻查 Gradle 缓存、打开错误的 JAR,或放弃尝试。
- 解锁任务委派,处理涉及内部 SDK 的复杂任务;这些任务以前只能由你亲自完成。
实际效果对比
不使用 jvmsrc(盲目折腾 25 轮)
用户: 重写
AbstractTradingService中的审计钩子——它有可复用的公共实用方法吗?Agent:
- 在工作区中搜索 AbstractTradingService.java ➔
0 hits- 运行:
find ~/.gradle -name "trading-core*"- 找到 4 个版本:
2.1.0、2.3.0、2.4.1、3.0.0-SNAPSHOT- 猜测: 选中
trading-core-2.4.1.jar(项目实际使用的是3.0.0-SNAPSHOT!)- 运行: 对错误的 JAR 执行
jar tf和javap -p- [22 轮后] “我没看到实用方法,你得自己实现。”
实际情况:
3.0.0-SNAPSHOT新增了maskSensitiveFields(),正是针对这种情况的受保护辅助方法。Agent 并没有产生幻觉——它只是看不到。
使用 jvmsrc(3 轮即可立即解决)
用户: 重写
AbstractTradingService中的审计钩子——它有可复用的公共实用方法吗?Agent:
search_classes("AbstractTradingService")➔ 找到 FQN 和精确解析出的库。get_class_structure(scope: "overview")➔ 在3.0.0-SNAPSHOT中发现maskSensitiveFields()。get_method_signature("maskSensitiveFields")➔ 获取准确的签名和泛型。结果: 首次尝试就正确编写了重写代码。无需遍历缓存、无需猜测、不会用错版本。
工作原理
- 构建工具查询:
jvmsrc会向你当前使用的构建工具(例如 Gradle)查询精确解析后的类路径配置。 - **智能缓存:**它会缓存解析后的类路径,并跟踪构建文件的变更以保持最新。
- **精准 AI 工具:**它不倾倒完整代码,而是提供精准、高粒度的工具(签名、结构、搜索),以缩小上下文窗口并将令牌用量降至极低。
安装与快速入门
1. 安装 CLI
npm install -g jvmsrc
或者通过 npx 直接使用:
npx jvmsrc mcp
重要
需要 Node ≥ 20,且 Java 必须位于PATH中(用于 CFR 反编译器和javap)。
2. 添加 MCP 服务
将以下内容粘贴到你的 AI 助手配置中(Cursor、Claude Code、Windsurf 等),然后重启宿主:
{
"mcpServers": {
"jvmsrc": {
"command": "jvmsrc",
"args": ["mcp"]
}
}
}
可选:运行 jvmsrc config(或 jvmsrc config --project /path/to/gradle-project),即可打印可直接粘贴的配置块和环境提示。大多数用户可以跳过此步骤,直接复制上面的代码片段。
MCP 服务参考
MCP 服务通过 jvmsrc mcp 使用 stdio 运行。默认配置无需环境变量:
{
"mcpServers": {
"jvmsrc": {
"command": "jvmsrc",
"args": ["mcp"]
}
}
}
私有仓库凭据(可选)
仅当你的 Gradle 构建需要凭据环境变量才能访问私有 Maven/Artifactory/Nexus 类仓库时才需要。MCP 宿主通常不会继承你的交互式 shell,因此必须在 jvmsrc MCP 进程上设置这些变量(然后重启服务)。
下面的 REPO_USER / REPO_PASS 仅为示例名称,并非 jvmsrc 必需。请使用项目 Gradle 脚本中说明的变量名称:
{
"mcpServers": {
"jvmsrc": {
"command": "jvmsrc",
"args": ["mcp"],
"env": {
"REPO_USER": "your-username",
"REPO_PASS": "your-password"
}
}
}
}
如果项目不需要这些变量,请完全省略 env 块。
Agent 可使用的工具
| 工具 | 功能 |
|---|---|
search_classes | 按简单名称或 glob 查找类;返回精简的 FQN + 库名称列表 |
get_class_structure | 获取类概览(用途 + 方法名称)或已声明的签名 |
get_method_signature | 获取方法真实的重载信息,包括参数名称和泛型 |
find_in_class_source | 在已解析的类中执行正则表达式或子字符串搜索 |
get_class_source | 获取方法体或行范围(作为最后手段使用) |
search_in_artifact | 在一个已解析依赖 JAR 的所有类中搜索文本 |
resolve_dependencies | 分析此项目实际使用的依赖关系图 |
提示
每个源码响应都包含sourceAvailable:真实源码(Javadoc、参数名称、泛型)对应true,CFR 反编译内容对应false(结构可靠,但名称可能是合成的)。
说明
**多模块:**省略modulePath后,jvmsrc 会自动选择唯一的所属模块;若未找到,则会列出候选modulePath。**方法:**如果索引包含源码增强信息,search_classes会匹配已声明的方法名称;若要搜索已知 JAR 中的方法体文本,请使用search_in_artifact。对于未匹配的名称,get_class_source的methodNames也会遍历超类。
让你的 Agent 使用它
工具描述很有帮助,但 Agent 通常更信任内置的 Bash 工具。只需添加两项简单配置,就能让 jvmsrc 成为依赖问题的默认选择。
1. 在 Agent 的指令中添加规则(CLAUDE.md、AGENTS.md、Cursor 规则)——许多客户端根本不会显示 MCP 服务的 instructions:
## Dependencies (jvmsrc)
For any question about a third-party library class, method or version, use the jvmsrc MCP tools
(search_classes → get_class_structure → get_class_source with methodNames; resolve_dependencies for versions).
When working inside one module, pass modulePath (':app' or the file you are editing) to get that module's versions.
Never use javap, unzip/jar on JARs, or ~/.gradle/caches. Code under this repo's src/ → grep/read as usual.
2.(Claude Code)通过钩子屏蔽 Shell 回退方案。 docs/hooks/block-jvm-fallbacks.mjs 会拒绝对 JAR 使用 javap、unzip/jar,以及访问 ~/.gradle/caches / ~/.m2,并告知 Agent 改用 jvmsrc,使其转而使用正确方案,而不是悄悄读取错误的版本。将脚本保存在稳定的位置,并添加到 .claude/settings.json(项目级)或 ~/.claude/settings.json(所有项目):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "node /absolute/path/to/block-jvm-fallbacks.mjs" }]
}
]
}
}
设置 JVMSRC_HOOK_DISABLE=1 可暂时关闭它。其他客户端有各自的钩子机制;移植前请查看其最新文档。
确认客户端会显示服务指令: 询问 Agent:“jvmsrc MCP 服务提供了哪些指令?” 如果它无法回答,请依赖步骤 1 中的规则。
说明
输入要求宽松。 可省略
projectRoot(将使用工作区,或设置JVMSRC_PROJECT_ROOT);modulePath接受app、/app、:app,或模块中的文件/目录(省略它或传入"*",即可搜索所有模块);className接受简单名称、Outer.Inner,或以.class/.java结尾的名称。项目上的首次调用会运行 Gradle(通常需要 5–10s);后续调用将使用缓存。只有在构建文件无法体现的内容发生变化后(例如重新发布了 SNAPSHOT),才传入forceRefresh: true。
对比
| 工具 | 方法 | 差距 |
|---|---|---|
缓存索引器 / ~/.gradle grep | 扫描全局缓存 | 无法获取各项目实际解析出的版本 |
静态解析器(例如 build.gradle 解析器) | 仅解析声明 | 会漏掉传递依赖、BOM 和动态版本 |
mcp-javadoc / 仅支持路径的 CFR | 用户手动提供 JAR 路径 | 不会自动解析构建和类路径 |
| Gradle MCP(Tooling API) | 面向任务/构建 | 未针对类路径准确的 FQN 源码查找进行优化 |
jvmsrc | 查询实际构建工具和缓存 | 为 Agent 提供版本准确的源码和签名 |
目标受众
主要面向使用 Gradle 的 Java + Spring Boot 项目。其他 JVM 语言(Kotlin、Scala)和 Android 目前也能尽力支持,未来将作为一等目标;详情请参阅 ROADMAP.md。
如果你使用 Maven 或 Bazel,目前已列入计划,但尚未发布。请为代码仓库点星或提交 issue,我会据此安排优先级。
详细参考
要求与兼容性
运行环境: Node.js ≥ 20,PATH 中需有 Java。
项目类型: JVM 代码库(Java、Kotlin、Scala、Groovy)。jvmsrc 调用的是构建工具,而不是编辑器。
| 构建系统 | 状态 |
|---|---|
| Gradle | 支持——包括多模块项目 |
| Maven、Bazel | 计划中(SPEC.md) |
将 -p / projectRoot 指向 Gradle 根目录(settings.gradle(.kts) 或根 build.gradle(.kts))。存在 ./gradlew 时使用它,否则使用 PATH 中的 gradle。仅含 Maven 的目录树会明确报错,提示不受支持。
已知限制
目前仍处于早期阶段;支持范围较窄:
| 领域 | 当前情况 |
|---|---|
| 构建工具 | 仅支持 Gradle |
| 集成方式 | Groovy 初始化脚本(--init-script)——不是 Gradle Portal 插件 |
| 类路径 | 标准 JVM 类路径,以及 Gradle 可提供的 Kotlin MPP jvm* 配置 |
| 输出 | Java 风格的 .java 文本(sources JAR、项目间 src,或 CFR) |
复合构建、仅限 Android 的项目布局和特殊配置尚未经过全面验证。请参阅 ROADMAP.md。
安全与隐私
* **无遥测。** * **仅限本地** — 缓存和诊断信息保留在磁盘上;绝不会写入项目根目录。 * **仅通过 argv 启动子进程**(不进行 Shell 插值)— 参见 [SECURITY.md](SECURITY.md)。 * 可选设置 `JVMSRC_ALLOWED_ROOTS`,以限制 jvmsrc 可以解析的项目。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
实用标志: -p / --project、--module(:core:api)、--configuration、--include-test、--force-refresh、--verbose(仅 Gradle stderr)、--method、--start-line / --end-line。
用于测试的仓库样例:
test/fixtures/gradle-smoke —
jvmsrc get com.smoke.Core -p test/fixtures/gradle-smoke --module :core。
故障排除
- 解析失败: 运行
jvmsrc diagnostics last(或jvmsrc diagnostics last 5) - 自定义 JDK 安装根目录: 使用
jvmsrc config jdk-roots add /path/to/jdks添加一次即可 - 排查 JDK 不匹配: 运行
jvmsrc doctor java -p /path/to/project - 升级 jvmsrc 后: 重启 MCP 主机
- 类路径过时: 运行
jvmsrc resolve --force-refresh
环境变量
| 变量 | 用途 |
|---|---|
JVMSRC_JAVA_HOME | 为 Gradle/CFR 子进程指定 JDK 主目录 |
JVMSRC_CONFIG_DIR | jvmsrc 全局配置目录(绝对路径) |
JVMSRC_CACHE_ROOT | 缓存根目录(绝对路径) |
JVMSRC_LOG_DIR | 诊断日志目录(绝对路径) |
JVMSRC_CALL_LOG | 1 = 将每次 MCP 工具调用追加为一行写入 calls.log(选择启用;参见 SPEC §6.3) |
JVMSRC_ALLOWED_ROOTS | 允许的 projectRoot 前缀 |
JVMSRC_PROJECT_ROOT | 当 MCP 工具未提供 projectRoot,且客户端未发送工作区根目录时使用的默认项目根目录(回退到工作目录) |
JVMSRC_MAX_SOURCE_OUTPUT_CHARS | 源代码正文最大长度(默认值:524288) |
JVMSRC_GRADLE_TIMEOUT_MS | Gradle 超时时间 |
JVMSRC_CFR_PATH | 自定义 CFR JAR |
各操作系统的默认值遵循 env-paths 约定。完整目录布局:参见 SPEC.md §6。
未设置 JVMSRC_JAVA_HOME 时,jvmsrc 会从常见路径自动发现本地 JDK,例如 ~/.jdks(IntelliJ)、~/.gradle/jdks、SDKMan、jenv、asdf 和操作系统专属的系统安装目录,也会查找通过 jvmsrc config jdk-roots ... 全局配置的 JDK 根目录。
AI Agent 评价
终于有一个不会让我反编译 JAR 的 MCP 了
“对于厌倦了大模型凭空捏造不存在的 Spring API 的人来说,这个工具简直令人惊艳。它确实会读取字节码,提供准确的类定义和源码查找,不再像以往那样靠‘感觉’猜测。
search_classes功能极其精准,而javap回退机制和细粒度的作用域控制(overview/declared/effective)也经过了周到设计,让复杂 JAR 的浏览变得轻松。它速度很快,找不到类时会如实说明,并且能妥善管理缓存。对于任何深受依赖地狱困扰的开发者来说,这都是必备工具——就像有一位真正喜欢阅读文档的资深工程师随时相助。” — Claude(AI 评审者)
项目文档
| 文档 | 内容 |
|---|---|
| SPEC.md | Schema、契约、CLI/MCP 详情 |
| CONTRIBUTING.md | 构建、测试、PR 说明 |
| RELEASING.md | 分支管理、语义化版本、npm 发布 |
| CHANGELOG.md | 版本历史 |
| ROADMAP.md | 状态和计划中的工作 |
| SECURITY.md | 漏洞报告 |
从源代码构建
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
完整的贡献者工作流程:CONTRIBUTING.md。
我开发 jvmsrc,是因为我总是遇到同一个难题:Agent 擅长编写 Java,却看不到实际的类路径。如果它能帮你省下和我一样反复折腾 25 轮的时间,那正是它存在的意义。发现了 Bug、有了想法,或者只是想说它帮到了你?欢迎提交 issue 或 PR——我会阅读每一条反馈。
许可证
MIT——详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。