mcpField
R
repo-pulse

repo-pulse

ローカル
github.com/hasanyelaldiバージョン管理01 週間前に更新

repo-pulse について

repo-pulseは、ローカルのGit履歴からレビューリスク、コード所有権、リリース変更などをまとめる読み取り専用のMCPサーバーです。エンジニアチームやAIアシスタント向けで、ネットワークやホスティングサービスのアカウントなしでオフライン動作します。

主な機能

  1. 01ブランチレビューの背景とリスク順位
  2. 02ホットスポットと連動ファイルの分析
  3. 03コード所有権とコントリビューターの分析
  4. 04リリースノートと参照先の比較
  5. 05古いブランチとコミット履歴の確認

活用シーン

  1. 01PR作成前のブランチリスク評価とレビュー担当者の確認
  2. 02頻繁に修正されるファイルや隠れた依存関係の特定
  3. 03コード所有権の集中や知識の不足箇所の把握
  4. 04リリースノートの草案作成と古いブランチの確認

MCP 対応

MCPクライアントに読み取り専用ツール、リポジトリ概要リソース、プロンプトを提供します。標準入出力で動作し、明示的に許可されたローカルGitリポジトリを分析します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"hasanyelaldi-repo-pulse": {
"command": "npx",
"args": [
"-y",
"repo-pulse-mcp"
],
"env": {
"REPO_PULSE_REPOS": "<REPO_PULSE_REPOS>",
"REPO_PULSE_TOOLS": "<REPO_PULSE_TOOLS>"
}
}
}
}
起動コマンドnpx -y repo-pulse-mcp
設定が必要な環境変数
REPO_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 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmrepo-pulse-mcp0.5.0

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

repo-pulse-mcp

CI npm MCP Registry Read-only License: MIT

Git の履歴を、AI アシスタントが行動に移せる回答に変えます。このブランチに潜むリスクは何か、誰にレビューを依頼すべきか、繰り返し問題が起きているファイルはどれか、前回のリリース以降に何が変わったかを確認できます。

repo-pulse は、ローカルの Git リポジトリ向けの読み取り専用のModel Context Protocol サーバーです。stdio で動作し、Node.js と git だけで使えます。リポジトリを変更することも、ネットワークにアクセスすることもありません。アシスタントに次のような質問をしてみてください。

  • 🔍 「これから PR を作成します。このブランチのリスクは何ですか?見落としていることはありますか?誰にレビューを依頼すべきですか?」
  • 🐛 「繰り返し問題が起きているファイルはどれですか?変更が集中しているのはどこですか?」
  • 👥 「課金モジュールに最も詳しいのは誰ですか?特定の一人に依存していませんか?」
  • 🔗 「このファイルといつも一緒に変更されるファイルはどれですか?」
  • 🚀 「前回のリリース以降に何が変わりましたか?リリースノートの下書きを作成してください。」
  • 🧹 「古いブランチはどれですか?すでにマージ済みのブランチはどれですか?」

GitHub、GitLab、Bitbucket などからクローンしたリポジトリでも、リモートが設定されていないリポジトリでも、あらゆるローカル Git リポジトリで動作します。プルリクエスト、イシュー、CI ステータスなどのプラットフォームデータは対象外です。

repo-pulse を使って vitejs/vite のブランチをレビューする Claude Code:リスクの高いファイル、関連ファイルの見落とし、レビュアー

vitejs/vite のブランチを、シェルを使わず repo-pulse だけでレビューする、実際の Claude Code セッションです。記録方法をご覧ください。

クイックスタート

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変更頻度でファイルを順位付けし、そのうちバグ修正だった変更の数も示します。types: ["fix"] を指定すると、繰り返し問題が起きているファイルを見つけられます
change_coupling同じコミットで繰り返し一緒に変更されるファイルの組み合わせを提示します。インポートからは分からない隠れた依存関係を見つけられます
👥 所有権とチーム
ツール回答する内容
knowledge_map 🆕ファイルやディレクトリに詳しい人を、最近の作業を重視して示します。バス係数や、特定の一人に依存しているファイルもわかります
code_age 🆕各ファイルが最後に変更されてからの期間、最も古いディレクトリ、最終編集者が退職したファイルを示します
contributor_summary期間内の作者ごとのコミット数を示します。必要に応じてパスを指定できます
🚀 リリースとブランチ
ツール回答する内容
release_notes_draft2つの参照の間にあるコミットをConventional Commitの種類ごとに分類し、Markdownで表示します
list_tags新しい順のタグ、HEAD上の最新リリース、未リリース分の量を示します
compare_refs2つのブランチ、タグ、またはコミットの先行・遅延数と、その間のコミットを示します
stale_branchesN日間コミットのないブランチと、それぞれがすでにマージされているかを示します
🕒 履歴とアクティビティ
ツール回答する内容
recent_activity過去N日間のコミットを示します。作者とパスで絞り込めます
commit_searchメッセージにチケットID、機能名、または任意のテキストが含まれるコミットを検索します
file_history1つのファイルのコミットと行数の統計を示し、名前変更を追跡します
📦 その他の機能
種類名前内容
リソースrepo://{name}/overview現在のブランチ、最新のコミット、最新のタグ、コミット数・ブランチ数・タグ数を示します
プロンプトreview_branch 🆕ブランチのレビューブリーフィングです。リスクのあるファイル、見落とされたファイル、レビュアー、チェックリストを示します
プロンプトrelease_notes 🆕最新のタグ以降のリリースノートを整え、次のバージョン候補を提案します
プロンプトownership_report 🆕ディレクトリの担当者、バス係数、リスクにさらされている知識と、次のステップを示します
プロンプトcleanup_branches 🆕古いブランチを「安全に削除可能」と「要判断」に分類し、コマンドも示します
プロンプトweekly_engineering_updateツールを使ってデータを収集し、アップデートを作成するようモデルを導きます

すべてのツールには readOnlyHint: true の注釈が付けられ、outputSchema が宣言されています。また、古いクライアント向けに structuredContent とJSONテキストブロックの両方を返します。すべての入力と出力については、ツールリファレンスをご覧ください。

会話例

あなた: feature/search の PR を作成しようと思っています。知っておくべきことはありますか?

アシスタント ( base: "main"、head: "feature/search" を指定して review_context を呼び出します): 4 件のコミットで6つのファイルが変更されています。特に注意が必要なのは src/api.ts です。過去6か月に main で14回変更され、そのうち6回はバグ修正でした。test/api.test.ts を見落としているかもしれません。このファイルは10件中9件のコミットで src/api.ts と一緒に変更されていますが、このブランチには含まれていません。おすすめのレビュアーは Alice です。これらのファイルに関する最近の知識の大部分を持っています。

あなた: src/billing/ に最も詳しいのは誰ですか? 特定の1人に依存していますか?

アシスタント ( path: "src/billing" を指定して knowledge_map を呼び出します): バス係数は 1 です。Carol が最近の知識の72%を持ち、14ファイル中11ファイルの主なオーナーです。そのうち9つは彼女だけに依存しています。2番手の Bob は18%と大きく差があります。次の請求関連の変更で Bob と Carol がペアを組めば、知識を広められるでしょう……

あなた: 長い間、誰も触っていないコードはどの部分ですか?

アシスタント ( minAgeDays: 365 を指定して code_age を呼び出します): ファイルの半数は18か月間変更されていません。最も古いディレクトリは src/legacy/(中央値で3.2年前)で、その中の41ファイルは、現在はこのリポジトリにコミットしていない人たちが最後に変更したものです。ここで知識が失われつつあります……

あなた: 今四半期の変更が多いのはどこですか? また、何度も壊れているのはどこですか?

アシスタント ( days: 90 を指定して file_hotspots を呼び出します): src/core/insights.ts は3人による23件のコミットで変更されており、ほかのファイルを大きく上回っています。そのうち9件は修正でした。分割したり、テストを追加したりするのに適した候補です……

あなた: 前回のリリース以降、何が変わりましたか?

アシスタント (デフォルトの最新タグから HEAD までを指定して release_notes_draft を呼び出します): v0.2.0 以降、14件のコミットがあります。破壊的変更が1件あり、設定ファイルが repo-pulse.json に移動しました。新機能は、アクティビティの作成者フィルターとブランチのマージ検出です。バグ修正は3件で、主に空のリポジトリに関するものです。GitHub のリリースに貼り付けられる Markdown の下書きはこちらです:……

あなた: いくつかのブランチを整理できますか?

アシスタント ( days: 30 を指定して stale_branches を呼び出します): 6つのブランチで30日以上コミットがありません。そのうち4つはすでに main にマージされているため、安全に削除できます:……

あなた: ( weekly_engineering_update プロンプトを選択します)

アシスタント ( recent_activity、contributor_summary、file_hotspots、stale_branches を呼び出します): ハイライト — …

会話は説明用の例です。名前と数値は架空のものです。

vite の未リリースの変更と古いブランチについて尋ねた、実際のセッションはこちらです:

Claude Code が repo-pulse を使って vitejs/vite の未リリースの変更と古いブランチを要約する様子

repo-pulse を選ぶ理由

GitHub、GitLab、git 自体に対応した MCP サーバーはすでにあり、シェルを使えるコーディングエージェントなら git log を直接実行できます。repo-pulse はそれらを置き換えるものではありません。異なる役割を担います。ローカルの git 履歴を回答に変換し、自動承認しても安全です。

repo-pulseGitHub / GitLab MCP汎用 git MCP / シェル
返す内容集約された分析プラットフォームの API オブジェクト生の git 出力
変更できるかいいえ、許可リストで制限通常は可能(トークンのスコープ次第)可能
トークンまたはネットワークが必要かいいえはいいいえ
ローカルおよび未プッシュのブランチを認識するかはいいいえはい
ホスティングプラットフォームなしで動作するかはいいいえはい
プルリクエスト、イシュー、CI を認識するかいいえはいいいえ

実際には、次のようなメリットがあります。

  • 手順が少なく、数値も正確です。「変更が集中しているのはどこですか?」「リリースノートには何を含めますか?」「マージ済みで古くなっているブランチはどれですか?」といった質問に答えるには、通常、複数のシェルコマンドと手書きの集計処理が必要で、気づかないうちに誤った結果になることもあります。repo-pulse はテスト済みのコードで集計し、適用したフィルターを示す決定的な JSON を返します。一部のツールは、単一の git コマンドでは得られない情報も提供します。review_context は、ブランチの変更量、修正履歴、変更の関連性、コードの所有者を 1 回の呼び出しでまとめます。
  • 検証可能な読み取り専用です。 すべてのツールに readOnlyHint が注釈され、git サブコマンドの許可リスト(セキュリティモデルを参照)によって実行が制限されているため、クライアントは毎回承認を求めずに実行できます。コミットやプッシュが可能なシェルや git サーバーに、同じ権限を与えることはないでしょう。
  • シェルがない環境でも役立ちます。 Claude Desktop のようなチャットクライアントでは git を実行できません。repo-pulse を使えば、エンジニアリングマネージャーやテックリードがリポジトリについて直接質問できます。
  • git で開けるものなら何でも使えます。 オフラインやエアギャップ環境でも、セルフホストのリポジトリやリモートのないリポジトリでも動作し、作成者のメールアドレスを返すこともありません。

プラットフォームの MCP サーバーの代わりではなく、併用してください。 プルリクエスト、イシュー、CI の状態も必要な場合は、GitHub または GitLab の MCP と組み合わせてください。すでにシェルを利用できるコーディングエージェントを使っていて、たまに git log を実行するだけなら、repo-pulse はおそらく必要ありません。

ベンチマーク

Claude Code(Sonnet 5.5)は、vite と express に関する同じ4つの質問に2回回答しました。1回目は読み取り専用シェルのみ、2回目は repo-pulse のみを使用しました。方法の詳細、回答、注意事項はbench/README.mdに記載されています。

質問シェル:ターン数 · 時間 · 結果repo-pulse:ターン数 · 時間 · 結果
過去90日間のホットスポット上位10件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 はトークンを節約できません。優れたモデルは簡潔なシェルパイプラインを書けますが、repo-pulse のツール定義には、セッションごとにトークンが必要だからです(現在の13個のツールで約4k)。一方、複数ステップの質問、正確な数値の取得、シェルのないクライアントでは力を発揮します。

要件

  • 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

リポジトリが設定されていない場合、サーバーは起動を拒否します。また、io.github.hasanyelaldi/repo-pulse-mcp として MCP Registry にも掲載されています。

ツールの選択

有効にしたツールの定義は、セッションごとにトークンを消費します。13個すべてで約4kです。一部のツールだけが必要な場合は、機能に記載されているグループ、個別のツール名、またはその両方を使い、--tools(または REPO_PULSE_TOOLS)で必要なものだけを有効にしてください。

ツールセットツール定義
reviewreview_context、file_hotspots、change_coupling約1.3kトークン
ownershipknowledge_map、code_age、contributor_summary約950トークン
releasesrelease_notes_draft、list_tags、compare_refs、stale_branches約950トークン
historyrecent_activity、commit_search、file_history約800トークン
allすべて(デフォルト)約4kトークン
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 には、それが使用する4つのツールが必要です。

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 を追加してください。必要に応じて podman を docker に置き換えられます。このイメージは Docker 固有の機能を使用していません。MCP クライアントでは、podman を command に、残りを args に指定してください。

ツールリファレンス

すべてのツールでは、任意の引数 repo を指定できます。これはリポジトリの名前(概要リソースに表示されるディレクトリ名)または絶対パスです。デフォルトでは、最初に設定されたリポジトリが使用されます。

結果はコンパクトな JSON 形式です。コミット一覧には完全なハッシュではなく shortHash(リポジトリ内で一意に識別できる長さの、git の省略ハッシュ)が含まれます。これは ref を受け付ける場所ならどこでも使用できます。

review_context
InputTypeDefaultNotes
basestring–必須です。変更のマージ先となる対象 ref
headstringHEAD変更を含む ref
daysinteger180base の履歴をどこまで遡って読み取るか
halfLifeDaysinteger90knowledge_map と同様の、レビュアーに対する直近度の重み付け
excludestring[]–スキップする glob を最大 20 個指定できます。構文は file_hotspots と同じです
minSharedinteger2対応ファイルが欠落していると判定するための、共有コミットの最小数
minDegreeinteger50対応ファイルが欠落していると判定するための、結合度(%)の最小値
maxFilesPerCommitinteger30これを超える数のファイルに触れる履歴コミットはスキップされます(下記参照)
limitinteger201~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 }] }

base の履歴を参照しながら、base..head で変更されたファイルに対して file_hotspots、change_coupling、knowledge_map を組み合わせて実行する呼び出しです。

  • files は変更されたファイルの一覧で、リスクの高い順に並びます。base 上で修正回数が多いファイルが先になり、その後に変更回数が多いファイルが続きます。新しいファイルには履歴がないため、changes は 0、owner は null になります。
  • missingCompanions は変更されていないものの、変更されたファイルと通常一緒に変更されるファイルです(change_coupling と同じ degree)。忘れられた可能性のあるテストや設定ファイルなどが該当します。
  • reviewers は、変更されたファイルに関する直近の知識を重み付けして順位付けした一覧です。変更そのものの作成者は除外されます。share は、変更作成者を含む全員の知識に対する割合です。

変更されたファイルは、base..head にあるマージ以外のコミットから取得されます。そのため、あるファイルが変更された後に元に戻されていても、変更として数えられます。maxFilesPerCommit を超える数のファイルに触れるコミットも changes と fixes には含まれますが、所有権や結合度の計算対象にはなりません。名前の変更は追跡されません。

file_hotspots
InputTypeDefaultNotes
daysinteger901–3650
pathstring–サブツリーに限定します
excludestring[]–スキップするグロブを最大 20 個指定します。例:["*.lock", "dist/"]。/ がない場合は深さを問わず一致し、末尾が / の場合はディレクトリに一致します
typesstring[]–これらの Conventional Commits のタイプのみをカウントします。例:["fix"]
limitinteger101–100

出力:{ repo, windowDays, types, commitsScanned, scanTruncated, commitsMatched, fixesFromKeywords, filesChanged, hotspots: [{ path, changes, fixes, additions, deletions, authors, lastChanged }] }

マージコミットは除外され、ファイル名の変更は追跡されないため、名前を変更したファイルは新規ファイルとして扱われます。名前の変更をまたいで単一のファイルを追跡するには、 file_history を使用してください。

fixes は、changes のうちバグ修正だったコミット数です。頻繁に変更され、その多くが修正によるファイルは、単に大きくなるだけのファイルよりも、リファクタリングの有力候補です。 types: ["fix"] を指定すると修正のみがカウントされるため、ランキングには繰り返し問題が発生するファイルが表示されます。 コミットタイプは Conventional Commits のヘッダー(fix(api): …)から判定されます。ヘッダーがないコミットは、件名に「fix」、「bug」、「hotfix」のいずれかが含まれる場合に修正としてカウントされます。fixesFromKeywords はこの方法で見つかった修正数を示すため、値が 0 以外の場合、件数は推定値です。ヘッダーが常に優先されるため、docs: fix typo は修正として扱われません。

change_coupling
InputTypeDefaultNotes
daysinteger901–3650
filestring–このファイルを含むペアのみに限定します
pathstring–サブツリーに限定します
excludestring[]–スキップするグロブを最大 20 個指定します。file_hotspots と同じ構文です
minSharedinteger2ペアを一覧表示するために必要な共有コミットの最小数
maxFilesPerCommitinteger30これを超える数のファイルに触れるコミットはスキップされます
limitinteger101–100

出力:{ repo, windowDays, commitsScanned, scanTruncated, commitsSkipped, pairCount, pairs: [{ fileA, fileB, sharedCommits, revisionsA, revisionsB, degree }] }

degree は、各ファイルに触れたコミット数の平均に対する共有コミット数の割合です。100 は、2 つのファイルが常に一緒に変更されることを意味します。互いをインポートしないファイル間で degree が高い場合、隠れた依存関係(重複したロジック、同期を保つ必要がある設定やフィクスチャ)が存在することを示している可能性があります。大量の名前変更やフォーマット処理など、多数のファイルに触れる大規模なコミットは、対象となるすべてのファイルを結び付けてしまうためスキップされます。マージコミットは除外され、名前の変更は追跡されません。

knowledge_map
InputTypeDefaultNotes
pathstring–ファイルまたはサブツリー。リポジトリ全体を対象にする場合は省略します
daysinteger3651~3650
halfLifeDaysinteger90経過日数が N 日増えるごとに、コミットの重みが半分になります
excludestring[]–スキップするグロブを最大20個指定します。file_hotspots と同じ構文です
maxFilesPerCommitinteger30これを超える数のファイルに変更を加えたコミットはスキップされます
limitinteger101~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 日ごとに半分になるため、先月モジュールを作り直した人は、3年前に作成した人より高く評価されます。行数は考慮されないため、生成された差分やフォーマット変更の差分が過度に影響することはありません。share と ownerShare は割合を示します。busFactor は、その領域の知識の半分超を合わせて保有する作者の最小人数です。concentratedFiles は、1人の作者が80%以上を保有するファイル数です。files には変更頻度の高いファイルが先に表示され、主要な所有者も示されるため、パスに対するレビュアーの候補をすばやく確認できます。マージコミットは除外され、名前変更は追跡されません。

code_age
InputTypeDefaultNotes
pathstring–ファイルまたはサブツリー。リポジトリ全体を対象にする場合は省略します
minAgeDaysinteger0この日数以上経過したファイルのみを一覧表示します。概要にはすべて含まれます
inactiveDaysinteger180この期間コミットしていない作者は非アクティブとみなされます
excludestring[]–スキップするグロブを最大20個指定します。file_hotspots と同じ構文です
limitinteger201~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 直下の最初のディレクトリ階層(その直下にあるファイルの場合は .)ごとにグループ化し、中央値が古い順に並べます。これにより、もう誰も作業していないコードの領域がわかります。 lastAuthorActive は、その作者が inactiveDays の期間リポジトリ内のどこにもコミットしていない場合に false になります(マージも含みます)。inactiveAuthorFiles はそのようなファイルの数で、失われた知識のおおよその目安です。同じメールアドレスで複数の名前を使ってコミットした人は、1人として数えられます。

HEAD 上のファイルは、first-parent の履歴における追加と削除から判定されるため、マージによって追加または削除されたファイルも正しく処理されます。履歴は最大20,000コミットまで読み込まれます。それを超えると scanTruncated は true になり、カットオフより前に最後に変更されたファイルは含まれません。

contributor_summary
InputTypeDefaultNotes
daysinteger301~3650
includeMergesbooleanfalseマージもカウントします
pathstring–サブツリーに絞り込みます
limitinteger201~100

出力:{ repo, windowDays, totalCommits, scanTruncated, contributorCount, contributors: [{ author, commits, firstCommit, lastCommit }] }

release_notes_draft
InputTypeDefaultNotes
fromstringto より前の最新タグ排他的。タグ、ブランチ、またはコミットハッシュ
tostringHEAD包含
formatstringmarkdownmarkdown、sections、または both

出力:{ repo, from, to, commitCount, truncated, markdown?, sections?: [{ key, title, entries: [{ shortHash, scope, description, author }] }] }

markdown はそのまま貼り付けられる下書きです。sections は同じ内容を構造化データとして表します。両方を返すと結果が倍のサイズになるため、要求された形式のみが返されます。

セクションの順序:Breaking Changes、Features、Bug Fixes、Performance、Refactoring、Documentation、Tests、Build System、Continuous Integration、Chores、Reverts、Other Changes。 ヘッダーに !(feat!: …)があるコミット、または本文に BREAKING CHANGE: フッターがあるコミットは、破壊的変更として扱われます。破壊的変更のコミットは、該当する種類のセクションにも表示されます。マージコミットはスキップされます。

list_tags
InputTypeDefaultNotes
limitinteger201~200

出力:{ repo, totalTags, latestOnHead, commitsSinceLatest, tags: [{ name, date, shortHash, subject }] }

タグはタグの日付順(新しい順)に並びます。latestOnHead は HEAD から到達可能な最新のタグです。メンテナンスリリースが別のブランチでタグ付けされている場合、最も新しいタグとは異なることがあります。commitsSinceLatest はそのタグ以降のコミット数、つまり未リリースの作業数です。

compare_refs
InputTypeDefaultNotes
basestring–必須。比較対象の参照(例:main)
headstringHEAD比較する参照
limitinteger201~100。各コミット一覧に個別に適用されます

出力:{ repo, base, head, baseCommit, headCommit, ahead, behind, status, truncated, aheadCommits: [{ shortHash, author, date, subject }], behindCommits: [...] }

ahead は base にはなく head から到達可能なコミット数、behind はその逆の数です。status は identical、ahead、behind、diverged のいずれかです。両方の参照には release_notes_draft と同じ検証が適用され、コミット数にはマージコミットも含まれます。

stale_branches
InputTypeDefaultNotes
daysinteger30最新コミットの最低経過日数
includeRemotebooleanfalseリモート追跡ブランチも一覧表示します
mergedOnlybooleanfalseすでに HEAD にマージされたブランチのみ
limitinteger501~200

出力:{ repo, thresholdDays, totalBranches, staleCount, branches: [{ name, lastCommitDate, lastAuthor, daysSinceLastCommit, mergedIntoHead }] }

recent_activity
入力型デフォルト備考
daysinteger71~3650
authorstring–作者名の部分文字列。文字どおりに照合します
pathstring–リポジトリ相対のファイルまたはディレクトリ
limitinteger501~200

出力:{ repo, windowDays, totalCommits, truncated, commits: [{ shortHash, author, date, subject }] }

commit_search
入力型デフォルト備考
querystring–必須。大文字と小文字を区別せず、文字どおりに照合します。件名と本文が対象です
daysinteger–1~3650。省略すると全履歴を検索します
authorstring–作者名の部分文字列。文字どおりに照合します
pathstring–リポジトリ相対のファイルまたはディレクトリ
limitinteger201~100

出力:{ repo, query, windowDays, totalMatches, truncated, commits: [{ shortHash, author, date, subject }] }

file_history
入力型デフォルト備考
pathstring–必須。HEAD 時点のリポジトリ相対ファイル
limitinteger201~100

出力:{ repo, path, commitCount, truncated, renamed, commits: [{ shortHash, author, date, subject, path, additions, deletions }] }

ファイル名の変更を追跡するため、古いコミットではその時点でのファイルパスが報告されます。リストされたコミットが複数のパスにまたがる場合、renamed は true になります。マージコミットはスキップされます。バイナリファイルの場合、additions と deletions は null です。

リソース:repo://{name}/overview

設定済みリポジトリごとに 1 つのリソースがあります(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 が有効な場合はそれらも呼び出し、離職した人が最後に変更したファイルや、1 人が所有するホットスポットを明らかにします。knowledge_map が有効であれば利用できます。

プロンプト:cleanup_branches

引数(どちらも文字列で省略可能):days(デフォルトは30)、repo。Claude Code では:

/mcp__repo-pulse__cleanup_branches

モデルにstale_branchesを呼び出すよう指示し、結果を、削除しても安全なマージ済みブランチ(それぞれにgit branch -dコマンドを1つずつ付ける)と、判断が必要な未マージのブランチ(最終コミットの作成者を付ける)に分けます。コマンド自体は実行しないようモデルに指示します。stale_branchesが有効な場合に使用できます。

プロンプト:weekly_engineering_update

引数(どちらも文字列で省略可能):repo、days(デフォルトは7)。モデルに、どのツールを呼び出すか、ステークホルダー向けの短い更新情報をどのように構成するかを伝えるユーザーメッセージを生成します。

セキュリティモデル

このサーバーは、混乱したモデルや操作されたモデルが被害を与えられないように設計されています。

  • 厳密な読み取り専用です。 git の実行には単一の関数を使用し、log、rev-list、rev-parse、describe、for-each-refのみを許可します。それ以外は、プロセスの開始前に拒否されます。
  • シェルは一切使用しません。 git はchild_process.execFileと引数配列を使って起動するため、引数がシェルによって解釈されることはありません。
  • リポジトリの許可リストを使用します。 --repo/REPO_PULSE_REPOSで指定されたリポジトリのみを提供します。起動時にrealpath(シンボリックリンクを解決)でパスを正規化し、厳密に照合します。未知のリポジトリには、ディスク上に存在するかどうかにかかわらず、同じエラーが返されます。何も設定されていない場合、サーバーは起動しません(フェイルクローズ)。
  • 入力を検証します。 すべての入力は、上限を設定したzodスキーマを通します。参照はブランチ、タグ、ハッシュ、または~N/^Nのサフィックスの形式である必要があります。先頭の-、..による範囲指定、@{}や:の構文は許可されません。参照は--end-of-optionsの後に渡し、続いてrev-parse --verifyで解決します。パスは..セグメントを含まない相対パスである必要があり、--literal-pathspecsを付けて--の後に渡します(グロブ展開なし)。作成者のフィルターには--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

設計上の留意点:

  • プロセスの入出力と解析を分離しています。 プロセスを起動するのはrunner.tsだけです。parsers.tsとrelease-notes.tsは純粋関数であり、文字列のフィクスチャを使ってテストされます。
  • 曖昧さのない出力形式です。 gitの出力には、コミットの件名やファイル名に含まれる場合があるタブや改行ではなく、ASCIIの単位区切り文字(0x1f)とレコード区切り文字(0x1e)を使います。
  • テスト可能な構成です。 createServer()は依存関係(許可リスト、gitランナー、時計)を引数として受け取るため、テストでは固定の「現在時刻」を使ってインメモリトランスポートに接続できます。
  • エラーをツールの結果として返します。 検証エラーやgitの失敗は、対応方法が分かるメッセージを含むisError: trueのツール結果として返されます。そのため、セッションを失敗させるのではなく、モデルが自ら修正できます。
  • stdoutは厳守します。 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。リリースワークフローがすべてのチェックを実行し、provenance 付きで 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 の Web UI が開きます。スクリプトによるチェックには、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 トークンを消費します。そのため、単発の簡単な質問ではシェルのほうがコストを抑えられる場合があります(ベンチマークを参照)。ツールの選択を使うと、 使用するグループだけに絞れます。
  • 今後のアイデア:チームでの利用に向けた HTTP トランスポート。

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。