msr-mcp——挖掘软件库mcp服务器
分析您的git历史记录,并向任何兼容MCP的AI客户端公开MCP工具 (Claude Desktop、Cursor等)可以直接在存储库内调用。

______________________________________________________________________
工具
| 工具 | 它做什么 |
|---|---|
get_summary | 回购概述:提交次数、日期范围、更改最多的文件 |
get_hotspots | 按更改频率×复杂度排名的顶级文件(支持路径/扩展名过滤器) |
get_temporal_coupling | 最常一起更改的文件对 |
get_file_coupling | 特定文件的耦合伙伴 |
get_coupling_clusters | 经常一起更改的文件组(共同更改集群) |
get_file_commit_history | 使用JIRA段塞提取和过滤器提交一个文件的历史记录 |
get_file_authors | 按特定文件的提交次数排名的作者(知识所有者) |
get_bus_factor | 一个作者主导提交的文件(知识孤岛) |
get_ownership | 按提交次数或行数显示每个文件的主要作者 |
get_churn | 按添加和删除的总行数排名的顶级文件 |
get_stale_files | N天内未更改的文件,按复杂性加权 |
get_index_status | 当前索引状态(在仍在构建索引时有用) |
refresh_index | 重建完整 .msr/ 从头开始索引 |
只有 默认分支 (main → master → HEAD)被索引。
语言支持
完整的指标(变化频率、LOC、圈复杂度和认知复杂度)可用于 Java 只有PMD驱动复杂性分析。PMD 7的Kotlin支持尚未公开度量API,因此Kotlin仅获得LOC。所有其他基于文本的语言(TypeScript、Go、Python等)也会获得更改频率和LOC;完全跳过二进制文件。
______________________________________________________________________
先决条件
- Java 25+
PATH - Jbang (适用于零结账使用)
______________________________________________________________________
用法
选项A-Claude CLI(claude mcp add)
在Claude Code中注册msr-mcp的最快方法。
来自最新的GitHub版本 (推荐):
# Download the JAR once
curl -L https://github.com/mfietz/msr-mcp/releases/latest/download/msr-mcp-server.jar \
-o ~/bin/msr-mcp-server.jar
# Register for all your projects (user scope)
claude mcp add --scope user msr-mcp -- java -jar ~/bin/msr-mcp-server.jar来自当地建筑:
claude mcp add --scope user msr-mcp -- java -jar /path/to/msr-mcp/target/msr-mcp-server.jar服务器继承了Claude Code的工作目录,这是您运行时的repo根目录 claude 在git存储库中。使用 --scope project 相反,将配置检查到仓库中 .mcp.json (注意:JAR路径将是特定于机器的)。
______________________________________________________________________
选项B--JBang(无需结账)
jbang msr-mcp@mfietz/msr-mcp选项C——从源代码构建
git clone https://github.com/mfietz/msr-mcp.git
cd msr-mcp
mvn package -DskipTests
# JAR: target/msr-mcp-server.jar其他MCP客户端(克劳德桌面、光标等)
添加到客户端的MCP配置中,指向 workingDirectory 在您的git仓库中:
{
"mcpServers": {
"msr-mcp": {
"command": "java",
"args": ["-jar", "/path/to/msr-mcp-server.jar"],
"workingDirectory": "/path/to/your/git/repo"
}
}
}对于JBang,请更换 "command": "java" / "args": ["-jar", "..."] 随着 "command": "jbang" / "args": ["msr-mcp@mfietz/msr-mcp"].
______________________________________________________________________
索引存储
首次启动时,服务器会创建 .msr/ repo根目录中的目录:
.msr/
└── msr.db # SQLite database (WAL mode)添加 .msr/ 到 .gitignore (它已经在这个回购中了 .gitignore).
索引已更新 每次启动时递增 --只处理比上次索引提示更新的提交。呼叫 refresh_index 从零开始强制进行全面重建。
重命名的文件会被跟踪:重命名前的历史记录会被结转至新路径。已删除的文件将从复杂性度量表中删除,因此它们不再出现在热点或流失结果中。
______________________________________________________________________
工具参考
get_summary
没有争论。返回回购概述:
{
"totalCommits": 312,
"uniqueAuthors": 8,
"totalFilesTracked": 94,
"filesWithMetrics": 42,
"earliestCommitMs": 1704067200000,
"latestCommitMs": 1741046400000,
"topChangedFiles": [
{ "filePath": "src/main/java/com/example/Foo.java", "changeFrequency": 47 }
],
"topAuthors": [
{ "name": "Alice", "email": "alice@example.com", "commits": 120 }
],
"languageDistribution": [
{ "extension": ".java", "fileCount": 72 },
{ "extension": ".xml", "fileCount": 12 }
]
}get_hotspots
topN int Max results (default 20)
sinceEpochMs long Only include commits after this timestamp (ms)
extension string File extension filter, e.g. ".java". Default: all files
pathFilter string SQL LIKE path pattern, e.g. "src/service/%". Default: all paths返回一个按以下方式排序的JSON数组 hotspotScore 下降:
[
{
"path": "src/main/java/com/example/Foo.java",
"changeFrequency": 47,
"linesOfCode": 312,
"cyclomaticComplexity": 18,
"cognitiveComplexity": 24,
"hotspotScore": 0.93
}
]get_temporal_coupling
topN int Max results (default 20)
minCoupling double Min coupling ratio 0–1 (default 0.3)
fileFilter string SQL LIKE pattern, e.g. "%.java"
sinceEpochMs long Time window; triggers slower dynamic query when set没有 sinceEpochMs 快速预聚合 file_coupling 桌子被使用了。 随着 sinceEpochMs 基于CTE的查询直接在 file_changes (速度较慢)。
get_file_coupling
filePath string (required) Repo-relative path, e.g. "src/Main.java"
topN int Max partner files (default 10)
minCoupling double Min coupling ratio 0–1 (default 0.1)
sinceEpochMs long Time window; triggers slower dynamic query when set没有 sinceEpochMs 快速预聚合 file_coupling 桌子被使用了。 随着 sinceEpochMs 基于CTE的查询直接在 file_changes (速度较慢)。
返回与给定文件一起更改最频繁的文件:
[
{
"partnerPath": "src/service/OrderService.java",
"coChanges": 12,
"targetTotalChanges": 15,
"partnerTotalChanges": 13,
"couplingRatio": 0.92
}
]get_coupling_clusters
使用双向耦合标识经常一起更改的文件组 (co_changes / MAX(total_a, total_b))排除与所有内容共同更改的中心文件。
两种模式:
- 全局扫描 (没有
filePath):联合查找所有边≥minCoupling,返回按平均耦合排序的所有簇。 - 单文件查找 (
filePathset):递归图遍历只返回包含该文件的集群——对于目标查询来说要快得多。
filePath string If set: return the cluster for this file. If absent: return all clusters.
minCoupling double Min bidirectional coupling ratio 0–1 (default 0.3)
minClusterSize int Min files per cluster (default 3, global mode only)
maxClusterSize int Max files per cluster; excludes god-clusters (no default)
pathFilter string SQL LIKE pattern; keeps clusters where ≥1 file matches, e.g. "src/auth/%"
topN int Max clusters to return (default 20, global mode only)
sinceEpochMs long Time window; triggers dynamic query when set[
{
"clusterIndex": 1,
"files": ["src/auth/AuthFilter.java", "src/auth/LoginService.java", "src/auth/TokenStore.java"],
"edges": [
{ "fileA": "src/auth/AuthFilter.java", "fileB": "src/auth/LoginService.java",
"coChanges": 18, "couplingRatio": 0.82 }
],
"avgCoupling": 0.76
}
]get_file_authors
filePath string (required) Repo-relative path, e.g. "src/Main.java"
topN int Max authors to return (default 10)
sinceEpochMs long Only include commits after this timestamp (ms)返回按给定文件的提交次数排名的作者:
[
{ "authorEmail": "alice@example.com", "authorName": "Alice", "commitCount": 42 },
{ "authorEmail": "bob@example.com", "authorName": "Bob", "commitCount": 7 }
]get_bus_factor
topN int Max results (default 20)
threshold double Min dominance ratio 0–1 (default 0.75)
pathFilter string SQL LIKE path pattern, e.g. "src/service/%"
sinceEpochMs long Only include commits after this timestamp (ms)返回一个作者制作≥ threshold 在所有提交中,按 dominanceRatio 下降:
[
{
"filePath": "src/core/Engine.java",
"topAuthorEmail": "alice@example.com",
"topAuthorName": "Alice",
"topAuthorCommits": 38,
"totalCommits": 41,
"dominanceRatio": 0.93
}
]get_churn
topN int Max results (default 20)
sinceEpochMs long Only include commits after this timestamp (ms)
extension string File extension filter, e.g. ".java". Default: all files
pathFilter string SQL LIKE path pattern, e.g. "src/service/%". Default: all paths返回按总流失率(添加的行+删除的行)降序排列的文件:
[
{
"filePath": "src/main/java/com/example/Foo.java",
"linesAdded": 840,
"linesDeleted": 310,
"churn": 1150,
"changeFrequency": 47
}
]get_ownership
topN int Max results (default 20)
ownershipBy string Measure by "commits" (default) or "lines"
minOwnership double Min ownership ratio 0–1 (default 0.0)
extension string File extension filter, e.g. ".java". Default: all files
pathFilter string SQL LIKE path pattern, e.g. "src/service/%". Default: all paths
sinceEpochMs long Only include commits after this timestamp (ms)返回每个文件的主要作者,按所有权比率降序排列:
[
{
"filePath": "src/core/Engine.java",
"ownerEmail": "alice@example.com",
"ownerName": "Alice",
"ownerCount": 38,
"totalCount": 41,
"ownershipRatio": 0.93
}
]get_stale_files
长时间未更改的文件,按复杂性加权,可用于查找可能已腐烂的被忽略的代码。
topN int Max results (default 20)
minDaysStale int Only include files not changed for at least N days (default 180)
extension string File extension filter, e.g. ".java". Default: all files
pathFilter string SQL LIKE path pattern, e.g. "src/service/%". Default: all paths返回按过期分数排序的文件(daysSinceLastChange × complexity)下降:
[
{
"filePath": "src/legacy/OldParser.java",
"daysSinceLastChange": 540,
"ageInDays": 1200,
"linesOfCode": 420,
"cyclomaticComplexity": 31,
"stalenessScore": 0.95
}
]get_index_status
没有争论。返回背景索引的当前状态:
{ "status": "READY", "startedAtMs": 1741046400000, "elapsedMs": 4200, "errorMessage": null }status 是其中之一 NOT_STARTED, INDEXING, READY,或 ERROR。工具返回错误响应,而状态不是 READY.
get_file_commit_history
filePath string (required) Repo-relative path, e.g. "src/Main.java"
limit int Max commits (default 50)
sinceEpochMs long Only include commits after this timestamp (ms)
jiraSlug string Filter by JIRA slug; supports LIKE patterns, e.g. "PROJ-123" or "PROJ-%"refresh_index
没有争论。从头开始清除并重建整个索引。退货:
{ "status": "ok", "commitsProcessed": 1234, "filesIndexed": 89, "durationMs": 4200, "errorMessage": null }______________________________________________________________________
延伸阅读
模型上下文协议
- MCP官方文件 --规范、概念、快速入门
- MCP Java SDK --此服务器使用的源代码和示例
采矿软件库——书籍
- 亚当·托恩希尔, *你的代码作为犯罪现场* (Pragmatic Programmers,2015)——引入热点分析和时间耦合作为实用的重构指南
- 亚当·托恩希尔, *软件设计X射线* (Pragmatic Programmers,2018)——通过团队层面和架构分析扩展了该方法
实现类似想法的工具
学术背景
______________________________________________________________________
释放
推标签 v* 触发构建和附加胖JAR的发布工作流:
git tag v1.0.0 && git push origin v1.0.0