关于 repo-pulse
repo-pulse 是只读 MCP 服务,可将本地 Git 历史整理为代码审查风险、代码归属和版本变更等洞察,供工程团队与 AI 助手使用。它无需网络或托管平台账户,可离线运行。
主要功能
- 01分支审查背景与风险排序
- 02热点文件和协同变更分析
- 03代码归属与贡献者洞察
- 04版本说明和引用比较
- 05过期分支与提交历史工具
适用场景
- 01PR 提交前评估分支风险并寻找审查者
- 02发现频繁修复的文件和隐藏依赖
- 03识别代码归属集中及知识缺口
- 04起草版本说明并查找过期分支
MCP 相关
向 MCP 客户端提供只读工具、仓库概览资源和提示词。服务通过标准输入输出运行,并分析明确允许的本地 Git 仓库。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y repo-pulse-mcpREPO_PULSE_REPOSAbsolute paths of the git repositories to serve, separated by ':' (';' on Windows)REPO_PULSE_TOOLSComma-separated toolsets (review, ownership, releases, history) or tool names to enable; all tools by default本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
repo-pulse-mcp
将 Git 历史记录转化为 AI 助手可据此采取行动的答案:此分支有哪些风险、谁应该审查、哪些文件总是出问题,以及自上次发布以来有哪些变化。
repo-pulse 是一个面向本地 Git 仓库的只读 Model Context Protocol 服务。它通过标准输入/输出运行,只需要 Node.js 和 git,不会修改仓库,也不会访问网络。你可以向助手询问:
- 🔍 “我准备开一个 PR。有哪些风险、我遗漏了什么,以及谁应该审查?”
- 🐛 “哪些文件总是出问题?哪里改动最频繁?”
- 👥 “谁最了解计费模块?我们是否依赖某一个人?”
- 🔗 “哪些文件总是和这个文件一起变更?”
- 🚀 “自上次发布以来有哪些变化?起草发布说明。”
- 🧹 “哪些分支已过时,哪些已经合并?”
它适用于任何本地 Git 仓库,无论是从 GitHub、GitLab、Bitbucket 或其他地方克隆的,还是完全没有远程仓库的。拉取请求、问题或 CI 状态等平台数据不在其范围内。

一次真实的 Claude Code 会话:仅使用 repo-pulse,不用 shell,审查 vitejs/vite 的一个分支。请参阅录制过程。
快速开始
需要 Node.js 22.12+ 和 git。无需克隆或构建:服务直接通过 npm 运行。
# Claude Code: run inside the repository you want to ask about
claude mcp add repo-pulse -- npx -y repo-pulse-mcp --repo "$PWD"
然后询问 “自上次发布以来有哪些变化?”,或使用内置提示词审查你的分支:/mcp__repo-pulse__review_branch main。如需了解 Claude Desktop 和其他 MCP 客户端的配置,请参阅安装。
功能
共 13 个工具,按其回答的问题分组。🆕 表示最新工具。
🔍 代码审查与风险
| 工具 | 可回答的问题 |
|---|---|
review_context 🆕 | 一次调用即可为分支或 PR 提供简报:按过往改动频率和修复次数排序的变更文件、通常会与其一同变更但此次被遗漏的文件,以及审查者 |
file_hotspots | 按变更频率排序的文件,并列出其中有多少次变更属于 Bug 修复。types: ["fix"] 可找出总是出问题的文件 |
change_coupling | 在相同提交中总是一起变更的文件对:导入关系无法体现的隐藏依赖 |
👥 归属与团队
| 工具 | 可回答的问题 |
|---|---|
knowledge_map 🆕 | 谁熟悉某个文件或目录(近期工作权重更高),以及总线因子和依赖某个人的文件 |
code_age 🆕 | 每个文件距上次修改已有多久、最陈旧的目录,以及最后一位作者已离开的文件 |
contributor_summary | 某个时间段内每位作者的提交数,也可以指定某个路径 |
🚀 发布与分支
| 工具 | 可回答的问题 |
|---|---|
release_notes_draft | 两个引用之间按约定式提交类型分组的提交,以及 Markdown |
list_tags | 按时间从新到旧排列的标签、HEAD 上的最新发布版本,以及尚未发布的提交数量 |
compare_refs | 两个分支、标签或提交之间的领先/落后数量及其间的提交 |
stale_branches | N 天内没有提交的分支,以及每个分支是否已合并 |
🕒 历史与活动
| 工具 | 可回答的问题 |
|---|---|
recent_activity | 最近 N 天的提交,可按作者和路径筛选 |
commit_search | 提交说明中提及工单 ID、功能名称或任意文本的提交 |
file_history | 单个文件的提交记录及行数统计,并跟踪重命名后的文件 |
📦 还包括
| 类型 | 名称 | 功能 |
|---|---|---|
| 资源 | repo://{name}/overview | 当前分支、最后一次提交、最新标签,以及提交/分支/标签数量 |
| 提示词 | review_branch 🆕 | 分支审查简报:高风险文件、被遗忘的文件、审查者和检查清单 |
| 提示词 | release_notes 🆕 | 自上一个标签以来润色后的发布说明,并建议下一个版本 |
| 提示词 | ownership_report 🆕 | 目录的负责人、总线因子和知识风险,并提供后续步骤 |
| 提示词 | cleanup_branches 🆕 | 将陈旧分支分为可安全删除和需要决定两类,并提供命令 |
| 提示词 | weekly_engineering_update | 引导模型使用工具收集数据并撰写更新 |
所有工具都标注了 readOnlyHint: true,声明了 outputSchema,并同时返回
structuredContent 和 JSON 文本块,以兼容较旧的客户端。完整的输入和输出请参阅
工具参考。
示例对话
你: 我准备为
feature/search提交 PR。有什么需要注意的吗?助手 (调用
review_context,参数为base: "main"、head: "feature/search"):4 次提交 涉及 6 个文件。src/api.ts风险较高:过去六个月,它在main上变更了 14 次,其中 6 次是修复 Bug。你可能忘了test/api.test.ts:它在 10 次提交中有 9 次与src/api.ts一同变更,但不在此分支中。建议的审阅者: Alice,她掌握着这些文件近期的大部分相关知识。
你: 谁最了解
src/billing/?我们是否依赖某一个人?助手 (调用
knowledge_map,参数为path: "src/billing"):公交系数为 1。Carol 掌握着近期相关知识的 72%,并且是 14 个文件中 11 个文件的主要负责人;其中 9 个文件只有她一人了解。Bob 远远排在第二位,占 18%。下次修改账单功能时,让 Bob 和 Carol 搭档,有助于传播这些知识……
你: 哪些代码已经很久没人动过了?
助手 (调用
code_age,参数为minAgeDays: 365):一半的文件在过去 18 个月里都没有变更。src/legacy/是最老的目录(中位数为 3.2 年),其中有 41 个文件最后由已不再在此提交代码的人修改。知识正在从这里流失……
你: 本季度哪些地方变更频繁?哪些地方总是出问题?
助手 (调用
file_hotspots,参数为days: 90):src/core/insights.ts经 3 个人参与,变更了 23 次,远超其他文件,其中 9 次是修复。这很适合拆分或补充测试……
你: 自上次发布以来有哪些变化?
助手 (调用
release_notes_draft,使用默认值:最新标签 → HEAD):自 v0.2.0 以来共有 14 次提交。有一项不兼容变更:配置文件已移至repo-pulse.json。新功能包括活动记录的作者筛选和分支合并检测。还有 3 项 Bug 修复,主要针对空仓库。以下是可粘贴到 GitHub 发布页面的 Markdown 草稿:……
你: 我们能清理一些分支吗?
助手 (调用
stale_branches,参数为days: 30):有 6 个分支超过 30 天没有提交。其中 4 个已经合并到main,可以安全删除:……
你: (选择
weekly_engineering_update提示词)助手 (调用
recent_activity、contributor_summary、file_hotspots、stale_branches): 要点 — …
以上对话仅作示例:名称和数字均为虚构。
以下是在 vite 上进行的真实会话,询问尚未发布的变更和陈旧分支:

为什么选择 repo-pulse?
目前已有适用于 GitHub、GitLab 和 git 本身的 MCP 服务,而且具备 shell 的编码 Agent 可以直接运行 git log。repo-pulse 并不打算取代它们,而是承担不同的工作:它将本地 git 历史转化为答案,并且可以安全地自动批准。
| repo-pulse | GitHub / GitLab MCP | 通用 git MCP / shell | |
|---|---|---|---|
| 返回内容 | 汇总洞察 | 平台 API 对象 | 原始 git 输出 |
| 能否修改任何内容 | 不能,由允许列表强制限制 | 通常可以(取决于令牌权限范围) | 可以 |
| 是否需要令牌或网络 | 不需要 | 需要 | 不需要 |
| 能否查看本地和未推送的分支 | 可以 | 不可以 | 可以 |
| 是否支持不依赖托管平台的仓库 | 支持 | 不支持 | 支持 |
| 能否查看拉取请求、问题和 CI | 不能 | 可以 | 不能 |
实际意义如下:
- 步骤更少,数据准确。 像“变更集中在哪里?”“发布说明该写什么?”或“哪些分支已合并且已过时?”这样的问题,通常需要运行多条 shell 命令并手动编写计数管道,而这些操作可能会悄无声息地出错。repo-pulse 使用经过测试的代码进行计数,并返回确定性的 JSON,说明应用了哪些筛选条件。有些工具还能完成单条 git 命令做不到的事:
review_context一次调用即可综合某个分支的变更量、修复历史、变更关联和代码所有权。 - 可验证的只读操作。 每个工具都标注了
readOnlyHint,并受 git 子命令允许列表限制(参见安全模型),因此客户端无需每次都请求批准即可运行。你不会把同样的权限交给 shell 或能够提交和推送的 git 服务。 - 适用于没有 shell 的环境。 Claude Desktop 等聊天客户端无法运行
git。借助 repo-pulse,工程经理或技术负责人可以直接询问有关仓库的问题。 - 适用于 git 能打开的任何仓库。 它支持离线和气隙环境,也适用于可自托管或没有远程服务的仓库,并且绝不会返回作者的电子邮件地址。
应将它与平台服务搭配使用,而不是用它替代平台服务。 如果你还需要拉取请求、问题或 CI 状态,请将它与 GitHub 或 GitLab MCP 搭配使用。如果你使用的编码 Agent 已经具备 shell,且偶尔才需要运行 git log,那么你可能不需要 repo-pulse。
基准测试
Claude Code(Sonnet 5.5)针对 vite 和 express 的同样四个问题分别作答两次:一次只使用只读 shell,另一次只使用 repo-pulse。完整的方法、答案和注意事项请参阅 bench/README.md。
| 问题 | Shell:轮次 · 时间 · 结果 | repo-pulse:轮次 · 时间 · 结果 |
|---|---|---|
| 最近 90 天的十大热点 | 2 · 6.6 s · ✅ | 2 · 6.5 s · ✅ |
与 config.ts 耦合的文件 | 2 · 7.4 s · ❌ 统计偏少 | 2 · 8.6 s · ✅ |
| 最新版与前一版本的发布说明 | 3 · 14.0 s · ✅ | 3 · 12.5 s · ✅ |
| 已合并且 90 天未更新的分支 | 5 · 15.9 s · ✅ | 2 · 4.3 s · ✅ |
基准测试使用 v0.3.0(10 个工具)运行。坦诚地说:对于简单的一次性问题,repo-pulse 的 token 消耗并不更低,因为优秀的模型能写出精简的 shell 管道,而 repo-pulse 的工具定义在每个会话中都会消耗 token(当前 13 个工具约需 4k)。它在多步骤问题、准确获取数据,以及完全不提供 shell 的客户端中更有优势。
要求
- Node.js 22.12+
- git 2.24+(用于
--end-of-options)
安装
此软件包已发布到 npm,无需克隆或构建。此服务只会提供你明确允许的代码仓库。通过 CLI 参数或环境变量传入这些仓库(macOS/Linux 使用 : 分隔,Windows 使用 ;):
npx -y repo-pulse-mcp --repo ~/code/my-app --repo ~/code/my-lib
# or, as plain arguments
npx -y repo-pulse-mcp ~/code/my-app ~/code/my-lib
# or
REPO_PULSE_REPOS=~/code/my-app:~/code/my-lib npx -y repo-pulse-mcp
如果未配置任何代码仓库,此服务将拒绝启动。它也已在 MCP Registry 中登记为 io.github.hasanyelaldi/repo-pulse-mcp。
选择工具
每个启用工具的定义都会在每个会话中消耗 token,全部 13 个工具约需 4k。如果你只需要其中一部分,可使用 --tools(或 REPO_PULSE_TOOLS)仅启用所需工具;可以使用 功能 中的分组、单个工具名称,或两者组合:
| 工具集 | 工具 | 定义 |
|---|---|---|
review | review_context、file_hotspots、change_coupling | 约 1.3k token |
ownership | knowledge_map、code_age、contributor_summary | 约 950 token |
releases | release_notes_draft、list_tags、compare_refs、stale_branches | 约 950 token |
history | recent_activity、commit_search、file_history | 约 800 token |
all | 全部(默认) | 约 4k token |
npx -y repo-pulse-mcp --repo ~/code/my-app --tools review,list_tags
# or
REPO_PULSE_TOOLS=review,ownership npx -y repo-pulse-mcp ~/code/my-app
名称无效时,服务会在启动时停止,并列出所有有效名称。提示词依赖对应的工具:review_branch 需要 review_context,release_notes 需要 release_notes_draft,ownership_report 需要 knowledge_map,cleanup_branches 需要 stale_branches,而 weekly_engineering_update 需要它使用的四个工具。
Claude Code
在你要提问的代码仓库中运行:
claude mcp add repo-pulse -- npx -y repo-pulse-mcp --repo "$PWD"
Claude Desktop
编辑 claude_desktop_config.json(macOS:~/Library/Application Support/Claude/,Windows:%APPDATA%\Claude\),然后重启 Claude Desktop。请使用绝对路径:
{
"mcpServers": {
"repo-pulse": {
"command": "npx",
"args": ["-y", "repo-pulse-mcp", "--repo", "/absolute/path/to/your/repository"]
}
}
}
从源码安装
git clone https://github.com/hasanyelaldi/repo-pulse-mcp.git
cd repo-pulse-mcp
npm ci
npm run build
node build/index.js --repo /absolute/path/to/your/repository
Podman / Docker
podman build -t repo-pulse-mcp .
podman run -i --rm \
-v "$PWD:/repos/project:ro" \
-e REPO_PULSE_REPOS=/repos/project \
repo-pulse-mcp
代码仓库以只读方式挂载。在启用了 SELinux 的主机(Fedora、RHEL)上,请在卷选项中添加 ,Z。如果你更喜欢 Docker,可以将 podman 替换为 docker;此镜像未使用任何 Docker 专属功能。对于 MCP 客户端,将 podman 设为 command,其余部分设为 args。
工具参考
每个工具都接受可选的 repo 参数:仓库名称(目录名称,显示在概览资源中)或其绝对路径。默认使用第一个已配置的仓库。
结果为精简 JSON,提交列表包含 shortHash(git 的缩写哈希,长度足以在仓库中明确区分),而不是完整哈希;任何接受引用的位置都可以使用它。
review_context
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
base | string | – | 必填。更改将合并到的目标引用 |
head | string | HEAD | 包含更改的引用 |
days | integer | 180 | 回溯读取 base 历史的天数 |
halfLifeDays | integer | 90 | 审阅者的近期权重,与 knowledge_map 中相同 |
exclude | string[] | – | 最多 20 个用于跳过文件的 glob,语法与 file_hotspots 相同 |
minShared | integer | 2 | 缺失配套文件所需的最少共同提交数 |
minDegree | integer | 50 | 缺失配套文件所需的最低耦合度(%) |
maxFilesPerCommit | integer | 30 | 跳过涉及更多文件的历史提交(见下文) |
limit | integer | 20 | 1–100,分别应用于每个列表 |
输出:{ repo, base, head, baseCommit, headCommit, windowDays, commits, truncated, changeAuthors, filesChanged, additions, deletions, historyScanned, scanTruncated, files: [{ path, additions, deletions, changes, fixes, lastChanged, owner, ownerShare }], missingCompanions: [{ path, coupledWith, sharedCommits, degree }], reviewers: [{ author, share, filesKnown, lastCommit }] }
一次调用即可将 file_hotspots、change_coupling 和 knowledge_map 结合起来,针对 base..head 中更改的文件,并以 base 的历史为依据:
files是更改过的文件,按风险从高到低排列:先按在base上的修复次数排序,再按更改次数排序。新文件没有历史记录,因此changes为 0,owner为null。missingCompanions是未更改但通常会与已更改文件同时更改的文件(degree与change_coupling相同),例如可能被遗漏的测试或配置文件。reviewers按对已更改文件的近期加权了解程度排序,并排除更改的作者。share是相对于所有人的了解程度计算的,其中包括更改作者。
已更改的文件来自 base..head 中的非合并提交,因此,即使某个文件被更改后又改回,仍会计入。涉及文件数超过 maxFilesPerCommit 的提交仍会计入 changes 和 fixes,但不会计入所有权或耦合度。重命名不会被追踪。
file_hotspots
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
days | integer | 90 | 1–3650 |
path | string | – | 限定在某个子树范围内 |
exclude | string[] | – | 最多跳过 20 个 glob,例如 ["*.lock", "dist/"]。不含 / = 任意深度,末尾带 / = 目录 |
types | string[] | – | 仅统计这些 conventional-commit 类型,例如 ["fix"] |
limit | integer | 10 | 1–100 |
输出:{ repo, windowDays, types, commitsScanned, scanTruncated, commitsMatched, fixesFromKeywords, filesChanged, hotspots: [{ path, changes, fixes, additions, deletions, authors, lastChanged }] }
合并提交会被排除,重命名也不会被追踪,因此重命名后的文件会从头开始。要追踪单个文件的重命名历史,请使用
file_history。
fixes 统计 changes 中属于错误修复的提交数量:经常变更且多数变更都是修复的文件,比只是在不断增大的文件更适合作为重构候选项。使用 types: ["fix"] 时,只统计修复提交,因此排名会显示那些总是出问题的文件。
提交类型取自 conventional-commit 标头(fix(api): …)。如果提交没有此类标头,但主题中提到 "fix"、"bug" 或 "hotfix",则该提交会计为修复;fixesFromKeywords 会显示通过这种方式找到的修复数量,因此非零值意味着统计结果是估算值。标头始终优先,因此 docs: fix typo 不算修复。
change_coupling
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
days | integer | 90 | 1–3650 |
file | string | – | 仅包含与此文件相关的文件对 |
path | string | – | 限定在某个子树范围内 |
exclude | string[] | – | 最多跳过 20 个 glob,语法与 file_hotspots 相同 |
minShared | integer | 2 | 文件对要列出所需的最少共同提交数 |
maxFilesPerCommit | integer | 30 | 涉及文件数更多的提交会被跳过 |
limit | integer | 10 | 1–100 |
输出:{ repo, windowDays, commitsScanned, scanTruncated, commitsSkipped, pairCount, pairs: [{ fileA, fileB, sharedCommits, revisionsA, revisionsB, degree }] }
degree 是共同提交数占分别变更过每个文件的提交数平均值的百分比:100 表示两个文件总是一起变更。互不导入的文件之间若 degree 较高,通常意味着存在隐藏依赖(重复逻辑、必须保持同步的配置或测试夹具)。大型提交(例如批量重命名或格式调整)会被跳过,因为这类提交会让涉及的每个文件都产生关联。合并提交会被排除,重命名也不会被追踪。
knowledge_map
| Input | 类型 | 默认值 | 说明 |
|---|---|---|---|
path | string | – | 文件或子树;省略则表示整个仓库 |
days | integer | 365 | 1–3650 |
halfLifeDays | integer | 90 | 每经过 N 天,提交的权重减半 |
exclude | string[] | – | 最多 20 个要跳过的 glob,语法与 file_hotspots 相同 |
maxFilesPerCommit | integer | 30 | 跳过涉及文件数超过此值的提交 |
limit | integer | 10 | 1–100,分别应用于 authors 和 files |
输出:{ repo, path, windowDays, halfLifeDays, commitsScanned, scanTruncated, commitsSkipped, filesAnalyzed, busFactor, concentratedFiles, authors: [{ author, share, filesOwned, commits, lastCommit }], files: [{ path, owner, ownerShare, authors, commits, lastChanged }] }
每个修改文件的提交都会让其作者掌握该文件的相关知识,且每经过
halfLifeDays,权重就减半。因此,上个月重构某个模块的人,排名会高于三
年前编写该模块的人。此处不考虑代码行数,因此生成文件或重新格式化的差异不会占据过多权重。share 和
ownerShare 均为百分比。busFactor 是合计掌握该区域超过一半知识所需的最少作者人数;concentratedFiles 统计由一位作者掌握至少
80% 知识的文件数。files 按修改频率从高到低列出文件及其主要负责人,可快速用于为某个路径推荐审查者。排除合并提交,且不追踪重命名。
code_age
| Input | 类型 | 默认值 | 说明 |
|---|---|---|---|
path | string | – | 文件或子树;省略则表示整个仓库 |
minAgeDays | integer | 0 | 仅列出至少有这么久未变更的文件;摘要涵盖所有文件 |
inactiveDays | integer | 180 | 作者在这么长时间内没有提交,则视为不活跃 |
exclude | string[] | – | 最多 20 个要跳过的 glob,语法与 file_hotspots 相同 |
limit | integer | 20 | 1–100,分别应用于 directories 和 files |
输出:{ repo, path, inactiveDays, commitsScanned, scanTruncated, filesOnHead, medianAgeDays, ageBuckets: [{ label, files }], inactiveAuthorFiles, directories: [{ path, files, medianAgeDays, newestAgeDays }], files: [{ path, lastChanged, ageDays, lastAuthor, lastAuthorActive, commits }] }
对于 HEAD 上的每个文件,都会获取最后一个修改该文件的非合并提交的日期和作者。
ageBuckets 将文件划分为 30 天以内、30–90 天、90 天至 1 年、1–2 年和超过
2 年几个区间。directories 按 path 下的第一级目录对文件分组(直接位于该目录中的文件归入
.),并按中位文件年龄从大到小排列,以显示哪些代码部分已无人维护。
若作者在整个仓库中有 inactiveDays 天没有提交(合并提交也计入),则 lastAuthorActive 为 false;inactiveAuthorFiles 统计此类文件数,可粗略衡量已经流失的知识。使用同一邮箱、多个名称提交的人只计为一人。
HEAD 上的文件根据第一父提交历史中的新增和删除记录确定,因此合并提交本身新增或删除的文件也能正确处理。最多读取 20,000 个提交;超过此数量时,scanTruncated 为 true,且不会包含在截断点之前最后变更的文件。
contributor_summary
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
days | integer | 30 | 1–3650 |
includeMerges | boolean | false | 同时统计合并 |
path | string | – | 限定在某个子树范围 |
limit | integer | 20 | 1–100 |
输出:{ repo, windowDays, totalCommits, scanTruncated, contributorCount, contributors: [{ author, commits, firstCommit, lastCommit }] }
release_notes_draft
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
from | string | to 之前的最新标签 | 不包含。标签、分支或提交哈希 |
to | string | HEAD | 包含 |
format | string | markdown | markdown、sections 或 both |
输出:{ repo, from, to, commitCount, truncated, markdown?, sections?: [{ key, title, entries: [{ shortHash, scope, description, author }] }] }
markdown 是可直接粘贴的草稿;sections 是相同内容的结构化数据。只返回
请求的格式,因为两种格式同时返回会使结果大小翻倍。
分区顺序:重大变更、功能、错误修复、性能、重构、文档、测试、构建系统、
持续集成、杂项、回退、其他变更。如果提交标题中含有 !(feat!: …),或正文中有
BREAKING CHANGE: 页脚,则该提交属于重大变更;此类提交也会出现在其类型对应的分区中。跳过合并提交。
list_tags
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
limit | integer | 20 | 1–200 |
输出:{ repo, totalTags, latestOnHead, commitsSinceLatest, tags: [{ name, date, shortHash, subject }] }
标签按标签日期排序,最新的排在前面。latestOnHead 是可从 HEAD 到达的最新标签;
当维护版本在其他分支上打标签时,它可能与最新标签不同。
commitsSinceLatest 统计该标签之后的提交,即尚未发布的工作。
compare_refs
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
base | string | – | 必填。用于比较的引用(例如 main) |
head | string | HEAD | 要比较的引用 |
limit | integer | 20 | 1–100,分别应用于每个提交列表 |
输出:{ repo, base, head, baseCommit, headCommit, ahead, behind, status, truncated, aheadCommits: [{ shortHash, author, date, subject }], behindCommits: [...] }
ahead 统计可从 head 到达、但无法从 base 到达的提交;behind 则相反。status 为
identical、ahead、behind 或 diverged。两个引用都经过与
release_notes_draft 相同的验证,且计数包含合并提交。
stale_branches
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
days | integer | 30 | 最新提交的最小时间间隔 |
includeRemote | boolean | false | 同时列出远程跟踪分支 |
mergedOnly | boolean | false | 仅列出已合并到 HEAD 的分支 |
limit | integer | 50 | 1–200 |
输出:{ repo, thresholdDays, totalBranches, staleCount, branches: [{ name, lastCommitDate, lastAuthor, daysSinceLastCommit, mergedIntoHead }] }
recent_activity
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
days | integer | 7 | 1–3650 |
author | string | – | 作者姓名的子字符串,按字面匹配 |
path | string | – | 相对于仓库的文件或目录 |
limit | integer | 50 | 1–200 |
输出:{ repo, windowDays, totalCommits, truncated, commits: [{ shortHash, author, date, subject }] }
commit_search
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
query | string | – | 必填。按字面匹配,不区分大小写;匹配主题和正文 |
days | integer | – | 1–3650。省略则搜索全部历史 |
author | string | – | 作者姓名的子字符串,按字面匹配 |
path | string | – | 相对于仓库的文件或目录 |
limit | integer | 20 | 1–100 |
输出:{ repo, query, windowDays, totalMatches, truncated, commits: [{ shortHash, author, date, subject }] }
file_history
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path | string | – | 必填。相对于仓库的文件路径,以 HEAD 时的路径为准 |
limit | integer | 20 | 1–100 |
输出:{ repo, path, commitCount, truncated, renamed, commits: [{ shortHash, author, date, subject, path, additions, deletions }] }
会追踪文件重命名,因此较早的提交会报告文件当时的路径;当列出的提交涉及多个路径时,renamed 为 true。合并提交会被跳过;对于二进制文件,additions 和 deletions 为 null。
资源:repo://{name}/overview
每个已配置的仓库各有一个资源(通过 resources/list 列出,支持名称补全):
{
"name": "my-app",
"path": "/home/me/code/my-app",
"currentBranch": "main",
"detachedHead": false,
"lastCommit": { "hash": "…", "shortHash": "1a2b3c4", "author": "…", "date": "…", "subject": "…" },
"latestTag": "v0.2.0",
"commitCount": 412,
"branchCount": 7,
"tagCount": 9
}
提示词:review_branch
参数(字符串):base(必填,例如 main)、head(默认值为 HEAD)、repo。在 Claude Code 中,它是一个斜杠命令:
/mcp__repo-pulse__review_branch main feature/search
它会指示模型调用 review_context(以及在启用该工具时调用 compare_refs),并撰写审查简报:摘要、风险文件、可能遗漏的文件、建议的审查者,以及待核查事项清单。它还会告知模型,repo-pulse 返回的是历史记录而非差异,因此简报不能声称已阅读代码。只要启用了 review_context,此提示词便可用。
提示词:release_notes
参数(字符串,均为可选):from(默认值:to 之前的最新标签)、to(默认值为
HEAD)、version、repo。在 Claude Code 中:
/mcp__repo-pulse__release_notes
它会指示模型调用 release_notes_draft,并将分组后的提交改写为面向用户的发行说明:先列出重大变更,再列出功能和修复,省略内部杂项。未提供 version 时,它还会调用 list_tags(如果已启用),并建议下一个 semver 版本。只要启用了 release_notes_draft,此提示词便可用。
提示词:ownership_report
参数(字符串,均为可选):path(默认值:整个仓库)、repo。在 Claude Code 中:
/mcp__repo-pulse__ownership_report src/billing
它会指示模型调用 knowledge_map,并撰写一份关于负责人、巴士因子以及依赖单一人员的文件的报告,最后给出具体建议。启用 code_age 和 file_hotspots 后,它还会调用这两个工具,以标记最后由已离职人员修改的文件,以及由单人负责的热点文件。只要启用了 knowledge_map,此提示词便可用。
提示词:cleanup_branches
参数(均为可选字符串):days(默认值为 30)、repo。在 Claude Code 中:
/mcp__repo-pulse__cleanup_branches
它会指示模型调用 stale_branches,并将结果分为已合并且可以安全删除的分支(每个分支对应一条 git branch -d 命令),以及需要决定是否处理的未合并分支(附上最后一位作者)。模型会被告知不要自行运行这些命令。启用 stale_branches 后即可使用。
提示词:weekly_engineering_update
参数(均为可选字符串):repo、days(默认值为 7)。生成一条用户消息,告知模型要调用哪些工具,以及如何组织一份简短的利益相关者更新。
安全模型
此服务的设计目标是防止困惑或受操纵的模型造成损害:
- 严格只读。 git 通过单个函数运行,该函数只允许使用
log、rev-list、rev-parse、describe和for-each-ref。其他任何命令都会在进程启动前被拒绝。 - 绝不使用 Shell。 git 通过
child_process.execFile和参数数组启动,因此参数不会由 Shell 解释。 - 仓库允许列表。 只提供通过
--repo/REPO_PULSE_REPOS传入的仓库。启动时会通过realpath规范化路径(解析符号链接),并进行精确比对;无论未知仓库是否存在于磁盘上,都会返回相同的错误。如果未配置任何仓库,服务不会启动(默认拒绝)。 - 输入验证。 所有输入均通过带有边界限制的 zod 架构验证。引用必须符合分支、标签、哈希或
~N/^N后缀的格式:不能以-开头,不能包含..范围、@{}或:语法;它们会在--end-of-options之后传入,然后通过rev-parse --verify解析。路径必须是相对路径且不能包含..片段;它们会在--之后与--literal-pathspecs一起传入(不进行 glob 匹配)。作者筛选使用--fixed-strings,因此不会被视为正则表达式。 - 限制工作量。 每个工具的结果数量都有上限,扫描最多处理 5,000 条提交,git 输出上限为 16 MB,且每次 git 调用都会在 15 秒后超时。输出会注明是否发生截断。
- 强化 git 环境。 会移除继承的
GIT_*变量(例如GIT_DIR),禁用提示,关闭可选锁,强制关闭core.fsmonitor(否则仓库自身的配置可能会让 git 运行程序),并在计算差异时禁用外部 diff/textconv 驱动程序。 - 减少个人数据。 只返回作者姓名,不返回电子邮件地址。
不在范围内: 此服务信任 PATH 中的 git 二进制文件以及你加入允许列表的仓库。它是本地开发工具,没有网络传输功能,也不进行身份验证。
架构
src/
├── index.ts # stdio entry point: config → registry → server → transport
├── server.ts # MCP layer: tools, resource and prompt with zod schemas
├── config.ts # --repo / REPO_PULSE_REPOS parsing, repo allowlist (RepoRegistry)
├── errors.ts # InputError (safe to show) and GitError
├── core/
│ ├── insights.ts # one method per feature: builds git args, aggregates results
│ ├── glob.ts # exclude globs, matched in-process on paths git returned
│ └── release-notes.ts # pure conventional-commit parsing, grouping and Markdown
└── git/
├── runner.ts # the only place that spawns processes (allowlist, limits, env)
├── parsers.ts # pure parsers for git output (no I/O)
└── validation.ts # ref / path / author validation
设计说明:
- 将进程 I/O 与解析隔离。
runner.ts是唯一会启动进程的模块;parsers.ts和release-notes.ts是纯函数,通过字符串样例进行测试。 - 输出格式明确无歧义。 git 输出使用 ASCII 单元分隔符(
0x1f)和记录分隔符(0x1e),而不使用制表符或换行符,因为提交主题和文件名中可能包含这些字符。 - 组合方式便于测试。
createServer()将其依赖项(允许列表、git 运行器、时钟)作为参数,因此测试可以将它连接到具有固定“当前时间”的内存传输。 - 将错误转换为工具结果。 验证和 git 错误会以带有可操作消息的
isError: true工具结果呈现,让模型可以自我纠正,而不是导致会话失败。 - stdout 至关重要。 它承载 JSON-RPC,因此日志会写入 stderr,且 ESLint 会禁止使用
console.log。
基于官方 MCP TypeScript SDK v2(@modelcontextprotocol/server)构建。
开发
npm ci
npm run dev -- --repo . # run from source with tsx
npm test # unit + integration tests (vitest)
npm run lint # ESLint
npm run format # Prettier
npm run typecheck
npm run build # compile to build/
npm run check # everything CI runs
npm run inspect # build first; opens MCP Inspector against this repository
发布。 更新 package.json、server.json(两个 version 字段)中的版本,以及 src/server.ts 中的 SERVER_VERSION(如果它们不一致,单元测试会失败),然后合并并推送标签:
git tag -a vX.Y.Z -m vX.Y.Z && git push origin vX.Y.Z。发布工作流会运行完整检查,使用来源证明发布到 npm,并在 MCP Registry 中注册新版本。两者都使用 GitHub OIDC(npm Trusted Publishing 和 Registry 的 github-oidc 登录),因此不会存储发布令牌。如果只有 Registry 步骤失败,请手动运行工作流(gh workflow run release.yml):它会跳过 npm,并重试 Registry。
测试。 单元测试覆盖解析器、验证、配置解析和发布说明分组。集成测试会创建带有脚本化历史记录(虚构作者、固定日期)的临时 git 仓库,并测试每项功能,包括通过内存传输的真实 MCP 客户端进行直接测试和端到端测试,以及安全检查。
MCP Inspector。 npm run build && npm run inspect 会打开连接到此仓库的 Inspector 网页界面。脚本化检查也可以使用 CLI 模式:
npx @modelcontextprotocol/inspector --cli node build/index.js -e REPO_PULSE_REPOS="$PWD" \
--method tools/call --tool-name release_notes_draft
限制和想法
- 活动、热点和贡献者工具会检查从
HEAD可达的提交;未合并分支上的工作不会计入。 file_hotspots、change_coupling、knowledge_map、review_context和code_age不会跟踪重命名:重命名后的文件从重命名时起会被视为新文件。- 每个会话的工具定义约占用 4k 个令牌,因此,对于简单的一次性问题,使用 shell 可能更省(参见基准测试)。选择工具可将其限制为你会使用的工具组。
- 后续可能的工作:为团队使用添加 HTTP 传输。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。