@jokeran/java-repo-skimmer
v1.0.2
Published
Java repository intelligence MCP with unified query, call graph, data flow, Spring analysis, and incremental indexing.
Maintainers
Readme
Java Repo Skimmer MCP
面向多仓 Java 后端联查场景的本地代码智能 MCP。它会索引一个或多个 Java Git 仓库,让大模型以低 token、低延迟方式查询定义、调用关系、类型层次、数据流、Spring 依赖、影响面和代码证据。
当前版本:1.0.2
1.0.2 亮点
- 新增
java_query:用一个自然语言问题聚合符号、文本、调用图、数据流、Spring 和影响面证据,并隔离局部失败。 - 新增
java_trace_data_flow:支持 assignment、property read/write、parameter binding、return、conditional 和 fallback;可用scopeId隔离不同方法中的同名局部变量。 - 建立类型层次和 override graph,
java_trace_symbol可返回 override 目标。 - 增强 Spring 注入解析:支持
@Qualifier、@Resource、@Primary、候选歧义、证据级别和风险标记。 - 增量 precise 会区分 API 与方法体变化,并沿反向依赖选择性重算。
- 索引采用 generation 原子激活、跨进程写租约、崩溃恢复和 schema 校验,避免读到半成品。
- 查询统一接入时间、结果、节点、文件和读取字节预算,并返回取消、截断和部分结果诊断。
- watcher 支持退避重试、epoch 隔离和
WatchService自愈;查询和索引路径完成内存及 N+1 优化。 - npm 包内置 fat JAR,并提供干净安装后的 MCP 握手验证。
特性
stdio + MCP(JSON-RPC),无需部署服务器;核心分析服务兼容 Java 8。- 支持本地源码启动,也支持
npx @jokeran/java-repo-skimmer@latest。 - 支持多仓索引、repo-local SQLite、FTS5、增量刷新、缓存清理和健康解释。
heuristic适合日常快速定位;precise使用 JavaParser/SymbolSolver 提升调用关系精度。precise会尝试加载本机 Maven 缓存中的第三方 JAR;失败自动降级,不要求运行期安装 Maven。- watcher 默认关闭,仅在当前 MCP 进程内生效;macOS 默认带 30 秒轮询兜底。
- 支持低内存模式和无变化
fast_reuse,避免重复扫描解析全仓。
安装与使用
方式一:本地源码方式
适合开发和本机试用。
cd "/path/to/java-repo-skimmer"
./scripts/install.shMCP 配置:
{
"mcpServers": {
"java-repo-skimmer": {
"command": "/path/to/java-repo-skimmer/scripts/run.sh"
}
}
}方式二:npm wrapper 方式
适合发布给用户。发布到 npm 后,用户不需要 clone 仓库,也不需要自己构建。
{
"mcpServers": {
"java-repo-skimmer": {
"command": "npx",
"args": ["-y", "@jokeran/java-repo-skimmer@latest"]
}
}
}如果客户端要求 command 使用绝对路径,可以把 npx 改为本机 npx 的完整路径。
依赖说明
| 场景 | 需要 Java | 需要 Maven | 需要 Node |
| ------------------------------- | -------------: | -----------: | --------------------------: |
| 本地源码运行 scripts/run.sh | 是 | 否 | 否 |
| 本地源码构建 scripts/build.sh | 是,含 javac | 否,有则优先 | 否 |
| npm wrapper 运行 | 是 | 否 | 是,用于 npx 启动 wrapper |
| npm 发包前生成 fat jar | 是 | 否,有则优先 | 是 |
说明:npm wrapper 只负责下载和启动,真正的索引和查询仍由 Java 进程执行,运行期核心性能不会因为外层是 Node 而下降。
验证
./scripts/build.sh
./scripts/test.sh
./scripts/smoke.sh如需放宽 smoke 等待时间,可设置:
SMOKE_TIMEOUT_MS=60000 ./scripts/smoke.sh- 有 Maven 时,
test.sh会执行 JUnit。 - 没有 Maven 时,
test.sh会回退到脚本构建和 MCP smoke。 smoke.sh会验证 MCP 握手、工具列表、索引、查询、代码片段、状态解释和缓存清理。
发布前建议在带 Maven 的环境额外执行:
mvn test
npm run prepare:npm
npm pack --dry-run --ignore-scripts
npm publish --dry-run索引工作流
日常增量刷新:
cd "/path/to/workspace-root"
/path/to/java-repo-skimmer/scripts/reindex-fast.sh关键链路或大改动后全量精确刷新:
cd "/path/to/workspace-root"
/path/to/java-repo-skimmer/scripts/reindex-precise.sh脚本会自动判断目标目录:
- 目标目录本身是包含 Java 文件的 Git 仓库时,索引当前仓库。
- 目标目录不是 Git 仓库时,只检查一级子目录,并索引其中包含 Java 文件的 Git 仓库。
MCP 工具 java_index_repos 也支持同样逻辑:传 rootPath 自动发现一级子 Git 仓库,或显式传 repoPaths。
precisionMode=precise 会按顺序尝试:解析 repo 内 pom.xml、从 ~/.m2/repository 匹配已有 jar、必要时用约 5 秒短超时尝试 ./mvnw 或 mvn dependency:build-classpath。Maven 不存在、VPN/私服不可用或命令超时不会阻断索引,只会在结果中通过 precise_dependency_resolution、dependency_warnings、version_conflicts 等字段提示。
如果机器内存紧张,可在启动 MCP 前设置:
JAVA_REPO_SKIMMER_LOW_MEMORY=true ./scripts/run.sh低内存模式会降低索引 worker,并在 java_index_repos 结果中返回 low_memory_mode=true。
如需自动刷新索引,可显式调用 java_index_control,设置 action=start_watcher。watcher 默认只监听当前进程内已开启的 repo,修改 .java、pom.xml、build.gradle(.kts)、settings.gradle(.kts) 后会自动触发 heuristic 增量索引。macOS 默认每 30 秒做一次轻量轮询兜底。
索引完成后,默认缓存会写入每个 Git 仓库自己的本地目录:
<repo-root>/.agent/java-repo-skimmer/index.db建议在业务项目 .gitignore 中加入:
.agent/1.0.2 能力状态
当前版本已经完成以下工程闭环:
- 能区分 API 签名变化和 body-only 变化,并基于反向依赖执行 selective precise 重算。
- 支持类型关系、override graph、Spring 注入解析和作用域敏感的数据流索引。
- 支持统一查询预算、取消、截断与部分失败诊断,避免大仓查询失控。
- 索引持久化支持 generation 原子激活、跨进程写租约、崩溃恢复与 schema 校验。
- watcher 具备退避重试和服务自愈;npm 包具备干净安装后的握手门禁。
MCP 工具
当前通过 tools/list 提供 16 个工具。索引运维按风险合并为一个只读入口和一个写入入口:
| 工具 | 用途 | 关键入参 |
| ----------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| java_index_repos | 索引一个或多个 Java 仓库 | repoPaths?, rootPath?, force?, precisionMode? |
| java_query | 自然语言聚合符号、调用、数据流和框架证据 | question, repoPaths?, limit?, maxOutputChars? |
| java_find_symbol | 查单个 class/interface/enum/method/field | query, repoPaths?, types?, limit?, fuzzy?, includeRelatedSameName?, includeBody?, maxBodyLines? |
| java_find_and_read | 查符号并直接附带精简代码片段 | query, repoPaths?, types?, limit?, maxBodyLines? |
| java_find_symbols_batch | 批量查询多个符号并按 query 分组返回 | queries, repoPaths?, limit?, includeBody?, maxBodyLines? |
| java_get_call_graph | 查 callers/callees/both 调用关系 | symbolName, direction?, repoPaths?, exactMatch?, precisionMode? |
| java_trace_symbol | 聚合定义和调用点 | symbolName, repoPaths?, exactMatch?, precisionMode? |
| java_get_file_outline | 查看文件类、方法、字段轮廓 | repoPath, filePath |
| java_get_code_slice | 按符号或行号读取代码片段 | repoPath, filePath, symbolName?, startLine?, endLine? |
| java_search_text | 搜索业务词、SQL、常量、字段名,默认走 FTS5 | query, repoPaths?, caseSensitive? |
| java_list_endpoints | 提取 Spring MVC 路由表 | repoPaths?, limit? |
| java_trace_data_flow | 跟踪作用域敏感、属性敏感的数据流 | symbol, scopeId?, repoPaths?, limit? |
| java_trace_spring_bean | 提取 Spring Bean 定义和依赖 | beanName?, repoPaths?, limit? |
| java_method_impact_analysis | 分析方法副作用和风险标记 | symbolName, repoPaths?, exactMatch? |
| java_index_status | 只读查看覆盖、健康、仓库、解释或 watcher | action?, repoPaths?, maxErrorsPerRepo? |
| java_index_control | 开关 watcher、压缩或确认后清除索引 | action, repoPaths?, dryRun?, confirm?, confirmation? |
java_index_status.action 支持 summary、health、repos、explain、watcher。java_index_control.action 支持 start_watcher、stop_watcher、compact、clear。清除前建议先使用 dryRun=true;实际清除必须传 confirm=true,清除全部索引还必须传 confirmation="CLEAR_ALL_INDEXES"。
java_index_repos 在 precisionMode=precise 时还支持:
preciseStrategy=full:全量 precise。preciseStrategy=auto:只对 API 签名变化文件及其反向依赖调用方执行 selective precise。
preciseStrategy=auto 的结果会额外返回这些字段:
api_changed_filesbody_changed_filesdependent_precise_filesselective_precise_target_filesselective_precise_pending_filesfile_dependency_count
推荐使用方法
日常建议按下面这套顺序使用:
- 初次进入工作区或切分支后,先执行
java_index_repos- 日常默认:
force=false,precisionMode=heuristic - 大改动后复核:
force=false,precisionMode=precise,preciseStrategy=auto
- 日常默认:
- 用
java_find_symbol、java_search_text、java_get_file_outline快速定位入口 - 用
java_get_code_slice读取关键方法,不要一开始全量读大文件 - 影响面判断优先用:
java_trace_symboljava_get_call_graphjava_method_impact_analysis
- Spring 项目补充用:
java_list_endpointsjava_trace_spring_bean
- 想确认当前索引是否适合做精确增量和影响面判断时,调用
java_index_status:action=summary查看索引覆盖action=explain判断索引是否可用
查询补充建议:
java_find_symbol的query现在只接受单个符号。像TradePreV2RoutingDataDTO RoutingData这种空格拼接查询会直接返回结构化错误,避免误命中。- 如果要一次查多个符号,优先使用
java_find_symbols_batch,或把多个查询拆成多次java_find_symbol。 includeRelatedSameName=true适合排查 interface/impl/DAO 同名链路,不适合拿来做“方法体阅读”;要看实现细节优先用includeBody=true、java_find_and_read或java_get_code_slice。java_find_symbol现在优先保留 exact 命中;只有 exact 为 0 时才继续 prefix/fuzzy 扩展。像queryBill、queryProgress这类方法名,默认结果会比旧版更干净。- 多仓工作区里如果你已经知道目标仓,尽量传
repoPaths,能明显降低同名符号噪音。
推荐索引参数:
- 日常快速定位:
precisionMode=heuristic - 关键链路复核:
precisionMode=precise,preciseStrategy=auto - 全仓强制精确重建:
precisionMode=precise,preciseStrategy=full,force=true
推荐提示词
实现需求:
请使用 java-repo-skimmer MCP 辅助开发,不要全量读取仓库。
rootPath=/path/to/workspace-root
先调用 java_index_repos,force=false,precisionMode=heuristic。
再用 java_find_symbol / java_search_text 定位入口。
如果要一次查多个符号,改用 java_find_symbols_batch;如果要直接带方法体,优先 java_find_and_read 或给 java_find_symbol 传 includeBody=true。
用 java_get_code_slice 读取关键方法。
用 java_trace_symbol / java_get_call_graph 分析影响面。
如果是 Spring 项目,用 java_list_endpoints 查看接口路由,用 java_trace_spring_bean 查看 Bean 依赖。
改动高风险方法前,用 java_method_impact_analysis 查看字段读写、异常、事务和同步标记。
必要时用 precisionMode=precise 复核关键链路。查询逻辑:
请使用 java-repo-skimmer MCP 梳理 XXX 逻辑。
先索引 rootPath,再查入口、定义和调用链。
输出按“入口 -> 参数 -> 服务调用 -> DAO/SQL -> 返回值 -> 风险”组织,并给出 repo_path、file_path、line。缓存与调试
默认缓存文件:
<repo-root>/.agent/java-repo-skimmer/index.dbSQLite 开启 WAL 后,旁边可能出现 index.db-wal 和 index.db-shm,这是正常的运行时辅助文件。
如果 index.db 损坏,服务会自动备份为 index.corrupt.<timestamp>.db 并重建空库;之后重新索引即可。
如果 MCP 工具没有传 repoPaths/rootPath,服务会优先用 MCP 进程当前工作目录推导 Git 仓库,并读取该仓库 .agent/java-repo-skimmer/index.db。npm wrapper 会保留用户启动 MCP 时的工作目录,方便客户端在当前项目下直接查询。
从旧版本升级时,如果检测到旧全局缓存:
~/.java-repo-skimmer/index.db服务只会输出 warning,不会自动迁移。重新调用 java_index_repos 后会生成新的 repo-local 缓存。
AST YAML 调试落盘默认关闭。仅调试 parser 时开启:
JAVA_REPO_SKIMMER_AST_DUMP=true ./scripts/run.shwatcher 轮询兜底默认只在 macOS 开启。如需在其他平台开启或调整频率,可设置:
JAVA_REPO_SKIMMER_WATCH_POLL=true
JAVA_REPO_SKIMMER_WATCH_POLL_INTERVAL_MS=30000将 JAVA_REPO_SKIMMER_WATCH_POLL_INTERVAL_MS=0 可关闭轮询兜底,只保留 WatchService。
清理缓存统一使用 java_index_control。执行 action=clear 前先传 dryRun=true 查看删除范围;实际清理必须传 confirm=true,清理全部索引还必须传 confirmation="CLEAR_ALL_INDEXES"。
如果只是维护缓存,可使用:
{
"action": "compact",
"removeMissingRepos": true,
"vacuum": true,
"confirm": true
}compact 会移除已经不存在的仓库缓存,并在 vacuum=true 时让 SQLite 回收磁盘空间。
如需把缓存放到自定义目录,可设置:
JAVA_REPO_SKIMMER_DATA_DIR=/path/to/cache-dir ./scripts/run.sh设置该环境变量后,会使用自定义目录下的单个 index.db,适合 CI、临时调试或集中缓存;普通用户默认不需要设置。
真实仓库验证配置
真实业务仓库相关的验证脚本不再依赖某台开发机的绝对路径。默认会寻找
fixtures/real-world/ 下的四个示例仓库;实际使用时请明确配置业务仓库父目录:
JAVA_SKIMMER_REAL_WORKSPACE=/path/to/workspace npm run eval:complex-real
node scripts/verify_realworld.js
node scripts/verify_precise_all.js若仓库不在同一个父目录,可用操作系统路径分隔符传入完整列表:
JAVA_SKIMMER_REAL_REPOS="/path/perform-trade:/path/perform-trade-export:/path/perform-web:/path/perform-web-export" \
node scripts/verify_realworld.js可选的 JAVA_REPO_SKIMMER_JAR、JAVA_SKIMMER_MCP_COMMAND、
JAVA_SKIMMER_MCP_ARGS 和 JAVA_SKIMMER_VERIFY_CWD 分别用于覆盖被测 JAR、
MCP 启动命令、JSON 格式的命令参数数组和子进程工作目录。
npm 发布准备
当前项目已包含 npm wrapper。prepare:npm 在有 Maven 时优先使用 Maven fat JAR;没有 Maven 时会合并 out/ 与 lib/*.jar 生成可发布 JAR。正式发布前执行:
npm run prepare:npm
npm pack --dry-run
npm publish --access publicprepare:npm 会生成:
dist/java-repo-skimmer.jarnpm 包通过 bin/java-repo-skimmer.js 启动该 jar。
项目结构
bin/java-repo-skimmer.js npm wrapper 入口
pom.xml Maven fat jar 构建配置
scripts/build.sh 构建
scripts/run.sh 本地 MCP 启动
scripts/smoke.sh MCP 端到端 smoke
scripts/test.sh 本地验证入口
scripts/verify_config.js 真实仓库验证配置
scripts/reindex-fast.sh 增量 heuristic 索引
scripts/reindex-precise.sh 全量 precise 索引
src/main/java/io/github/jokeran/javareposkimmer/Main.java
src/main/java/io/github/jokeran/javareposkimmer/mcp/McpStdioServer.java
src/main/java/io/github/jokeran/javareposkimmer/index/IndexService.java
src/main/java/io/github/jokeran/javareposkimmer/index/IndexPersistence.java
src/main/java/io/github/jokeran/javareposkimmer/index/IndexStoreRouter.java
src/main/java/io/github/jokeran/javareposkimmer/index/JavaSourceParser.java
src/main/java/io/github/jokeran/javareposkimmer/index/PreciseJavaAnalyzer.java已知限制
precisionMode=precise依赖 JavaParser 对源码可解析;语法不完整文件可能进入failed_files。- 对复杂泛型、反射调用、动态代理等场景,静态调用边仍有边界。
java_get_file_outline目前返回轻量概览,后续可升级成真正骨架摘要。java_search_text当前优先走 FTS5 phrase 查询,适合精确业务词、SQL、常量和中文短语;极宽泛的多 token 搜索后续可继续增强 token OR/AND 查询策略。java_find_symbol不支持空格拼接的多符号查询;这类输入会返回结构化错误,请改用java_find_symbols_batch或拆成多次单符号查询。
参考
- MCP Java SDK 文档:modelcontextprotocol/java-sdk
- 官方 Java SDK 站点:Server docs
- 可借鉴项目:OpenGrok、Zoekt
CI 会在 JDK 8、11、17 和 Node.js 20 上执行 Maven/fallback 相关验证、性能门禁、MCP smoke、npm 包 smoke 及评估契约检查;真实业务仓库 gate 仍需通过 JAVA_SKIMMER_REAL_WORKSPACE 单独提供测试数据。
