GitIntel
Git Intelligence MCP Server — deep repository analytics computed locally from your commit history. No external APIs, no data leaves your machine.
What GitIntel Does
GitIntel surfaces the same insights that tools like CodeScene and GitPrime charge for
—
hotspots, temporal coupling, knowledge maps, churn analysis, complexity trends, risk
scoring, and more. Everything runs locally against your .git directory.
Change Hotspots
Find files changed most frequently — the top 4% contain 50%+ of bugs.
Code Churn
Detect code rewritten as fast as it's written. Churn ratio near 1.0 = instability.
Temporal Coupling
Hidden dependencies not visible in imports — files that always change together.
Knowledge Map
Who knows what, weighted by recency. Find the right reviewer, spot knowledge silos.
Complexity Trend
Track how files grow in lines, nesting depth, and functions over time.
Risk Assessment
Score changes 0–100 combining hotspot history, size, sensitivity, and spread.
Release Notes
Structured changelogs from conventional commits with breaking change detection.
Contributor Stats
Team dynamics, collaboration graphs, workload distribution, and knowledge silos.
System Architecture
GitIntel is a Node.js MCP server that communicates over stdio using
JSON-RPC 2.0. It calls Git via execFile (never exec) to
prevent shell injection. All operations are strictly read-only.
graph TD
Client["MCP Client<br/>Claude Code / Codex"]
Server["mcp-git-intel<br/>Node.js process"]
Git["Git CLI<br/>execFile, no shell"]
Repo[".git directory<br/>read-only"]
Client <-->|"stdio JSON-RPC 2.0<br/>MCP protocol"| Server
Server -->|"execFile with args array<br/>30s timeout, 50MB buffer"| Git
Git -->|"stdout/stderr"| Server
Git -->|"read-only operations"| Repo
subgraph ServerInternals ["Server Internals"]
direction TB
Transport["StdioServerTransport"]
McpServer["McpServer SDK"]
Tools["8 Tool Handlers"]
Resources["2 Resource Handlers"]
GitLayer["Git Layer<br/>executor, parser, repo"]
UtilLayer["Util Layer<br/>scoring, formatting"]
Transport --> McpServer
McpServer --> Tools
McpServer --> Resources
Tools --> GitLayer
Tools --> UtilLayer
Resources --> GitLayer
end
Data Flow
Every tool invocation follows the same pipeline: validate, execute, parse, score, format, return.
sequenceDiagram
participant C as MCP Client
participant S as Tool Handler
participant V as Validation (Zod)
participant G as Git Executor
participant P as Parser
participant Sc as Scoring Engine
participant F as Formatter
C->>S: callTool(name, args)
S->>V: Validate inputs
V->>V: validatePathFilter() / validateRef()
S->>G: gitExec(args, options)
G->>G: execFile('git', [...args])
G-->>S: stdout / stderr
S->>P: Parse git output
P-->>S: Structured data
S->>Sc: Calculate scores
Sc-->>S: Scored results
S->>F: Format tables and bars
F-->>S: Formatted text
S-->>C: CallToolResult
Module Dependency Graph
graph TD
index["src/index.ts<br/>Entry point"]
subgraph ToolsLayer ["Tools Layer"]
hotspots["hotspots.ts"]
churn["churn.ts"]
coupling["coupling.ts"]
knowledge["knowledge-map.ts"]
complexity["complexity.ts"]
risk["risk.ts"]
release["release-notes.ts"]
contributors["contributors.ts"]
end
subgraph ResourcesLayer ["Resources Layer"]
summary["summary.ts"]
activity["activity.ts"]
end
subgraph GitLayer ["Git Layer"]
executor["executor.ts<br/>execFile wrapper"]
parser["parser.ts<br/>Output parsers"]
repo["repo.ts<br/>Validation"]
end
subgraph UtilLayer ["Util Layer"]
scoring["scoring.ts<br/>Score algorithms"]
formatting["formatting.ts<br/>Output formatting"]
end
index --> hotspots & churn & coupling & knowledge & complexity & risk & release & contributors
index --> summary & activity
hotspots --> executor & repo & parser & formatting & scoring
churn --> executor & repo & formatting & scoring
coupling --> executor & repo & formatting & scoring
knowledge --> executor & repo & formatting & scoring
complexity --> executor & repo & formatting
risk --> executor & repo & formatting & scoring
release --> executor & repo & parser & formatting
contributors --> executor & formatting & scoring
summary --> executor
activity --> executor
repo --> executor
Entry Point Flow
graph TD
Start["main()"] --> ExpandHome["Expand ~ in repo path"]
ExpandHome --> CheckGit["checkGitVersion()"]
CheckGit -->|"< 2.20"| Fatal1["Exit: git version too old"]
CheckGit -->|">= 2.20"| ResolveRoot["resolveRepoRoot()"]
ResolveRoot -->|"not a repo"| Fatal2["Exit: not a git repository"]
ResolveRoot -->|"valid"| CreateServer["Create McpServer"]
CreateServer --> RegisterTools["Register 8 tools"]
RegisterTools --> RegisterResources["Register 2 resources"]
RegisterResources --> Connect["Connect StdioServerTransport"]
Connect --> Running["Server running on stdio"]
Running -->|"SIGINT / SIGTERM"| Shutdown["Graceful shutdown"]
All 8 Analysis Tools
Each tool returns formatted text with tables, score bars
[████████░░] 80, and actionable recommendations — not raw git output.
graph TD
subgraph ChangeAnalysis ["Change Analysis"]
H["hotspots<br/>Change frequency"]
CH["churn<br/>Write/rewrite ratio"]
CT["complexity_trend<br/>Complexity over time"]
end
subgraph DependencyAnalysis ["Dependency Analysis"]
CO["coupling<br/>Temporal coupling"]
end
subgraph TeamAnalysis ["Team Analysis"]
KM["knowledge_map<br/>Who knows what"]
CS["contributor_stats<br/>Team dynamics"]
end
subgraph RiskRelease ["Risk & Release"]
RA["risk_assessment<br/>Change risk scoring"]
RN["release_notes<br/>Changelog generation"]
end
| Tool | What it does | Key Insight |
|---|---|---|
hotspots |
Files that change most frequently | Top 4% of files contain 50%+ of bugs |
churn |
Code written then rewritten | Churn ratio near 1.0 = instability |
coupling |
Files that always change together | Hidden dependencies not in imports |
knowledge_map |
Who knows a file/dir best (recency weighted) | Find reviewers, spot silos |
complexity_trend |
How file complexity evolves over time | Catch files growing out of control |
risk_assessment |
Risk score 0–100 for changes | Hotspot + size + sensitivity + spread |
release_notes |
Structured changelog from conventional commits | Groups by type, extracts breaking changes |
contributor_stats |
Team dynamics, collaboration graph | Workload distribution, knowledge silos |
hotspots — Change Frequency Analysis
The top 4% of files by change frequency typically contain 50%+ of bugs. Use this to identify files needing refactoring, better test coverage, or architectural attention.
graph LR
A["git log --name-only<br/>--since=N days"] --> B["Count file appearances<br/>across commits"]
B --> C["Normalize to 0-100<br/>heat score"]
C --> D["Format table with<br/>score bars"]
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer (>0) | 90 | Days to look back |
limit |
integer (1–100) | 20 | Max results |
path_filter |
string | — | Filter to files under this path |
churn — Code Churn Analysis
High churn indicates instability, unclear requirements, or code that is hard to get right.
graph LR
A["git log --numstat<br/>--since=N days"] --> B["Sum additions/deletions<br/>per file"]
B --> C["Calculate churn ratio<br/>deletions / additions"]
C --> D["Sort by total churn<br/>format table"]
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer (>0) | 90 | Days to look back |
limit |
integer (1–100) | 20 | Max results |
path_filter |
string | — | Filter to files under this path |
coupling — Temporal Coupling Detection
Reveals hidden dependencies not visible in imports or type signatures.
graph LR
A["git log --name-only<br/>multi-file commits"] --> B["Build co-change<br/>matrix"]
B --> C["coupling = shared /<br/>min(A, B)"]
C --> D["Filter by threshold<br/>format pairs"]
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer (>0) | 90 | Days to look back |
min_coupling |
float (0–1) | 0.5 | Minimum coupling score |
min_commits |
integer (>0) | 3 | Minimum shared commits |
limit |
integer (1–50) | 20 | Max pairs |
path_filter |
string | — | Filter to path |
shared_commits / min(commits_A, commits_B). Uses min so that
if B always changes with A, coupling is 1.0 even if A changes independently.
knowledge_map — Who Knows What
Find the right reviewer. Identify knowledge silos. Plan team transitions.
graph LR
A["git log --numstat<br/>per-author stats"] --> B["Weight: 30% volume<br/>30% frequency"]
B --> C["Weight: 40% recency<br/>30-day half-life"]
C --> D["Score 0-100<br/>per author"]
D --> E["Bus factor =<br/>authors with score >= 30"]
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
string (required) | — | File or directory to analyze |
days |
integer (>0) | 365 | Days to look back |
complexity_trend — Complexity Over Time
Track how a file's complexity evolves. Catch files growing out of control before they become unmaintainable.
graph LR
A["git log for file"] --> B["Sample N points<br/>evenly across history"]
B --> C["git show hash:path<br/>at each sample"]
C --> D["Measure: lines, depth<br/>functions, long lines"]
D --> E["Format trend table<br/>with warnings"]
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
string (required) | — | File to analyze |
samples |
integer (3–30) | 10 | Time samples |
days |
integer (>0) | 180 | Days to look back |
risk_assessment — Change Risk Scoring
Score the risk of uncommitted changes or a commit range before merging. Combines four signals.
graph TD
D["git diff --numstat"] --> R["Risk Engine"]
L["git log --name-only<br/>90-day history"] --> R
R --> H["Hotspot Factor<br/>30% weight"]
R --> S["Size Factor<br/>25% weight"]
R --> SE["Sensitivity Factor<br/>30% weight"]
R --> SP["Spread Factor<br/>15% weight"]
H & S & SE & SP --> O["Overall Risk<br/>0-100 score"]
| Parameter | Type | Default | Description |
|---|---|---|---|
ref_range |
string | uncommitted | Git ref range (e.g. main..feature) |
Risk Thresholds
| Score | Level | Action |
|---|---|---|
| ≥ 70 | HIGH | Thorough code review required |
| ≥ 40 | MEDIUM | Standard review, extra testing |
| < 40 | LOW | Standard process |
Sensitivity Patterns
| Score | File Patterns |
|---|---|
| 100 |
.env, .pem, .key, .cert
|
| 90–95 | Auth, payment, credential, session files |
| 80 | Database, migration, schema files |
| 70 | Docker, CI/CD, Jenkinsfile |
| 60 | Config files |
| 0 | Everything else |
release_notes — Changelog Generation
Generate structured changelogs from conventional commits between two git refs.
| Parameter | Type | Default | Description |
|---|---|---|---|
from_ref |
string (required) | — | Starting ref |
to_ref |
string | HEAD | Ending ref |
group_by |
type|scope|author |
type | Grouping strategy |
contributor_stats — Team Dynamics
Comprehensive contributor analytics: activity, collaboration graph, knowledge silos, focus areas, and commit time patterns.
graph LR
A["git log --numstat"] --> B["Per-author profiles"]
B --> C["Collaboration graph<br/>shared files"]
B --> D["Knowledge silos<br/>sole contributors"]
B --> E["Focus areas<br/>top directories"]
B --> F["Activity timeline"]
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer (>0) | 90 | Days to look back |
author |
string | — | Filter to specific author |
MCP Resources
Resources provide static data that clients can read at any time (not invoked as tools).
git://repo/summary
Repository snapshot: branch, last commit, total commits, active contributors, top languages, age, remote URL.
git://repo/activity
Recent 50-commit activity feed with hash, relative date, author, subject, and change stats.
Installation
GitIntel is not published to npm. Clone, build, and register locally.
Prerequisites
- Node.js ≥ 18
- Git ≥ 2.20
Build from Source
git clone <repo-url> cd mcp-server npm install npm run build
Register with Claude Code
# Analyze current directory claude mcp add git-intel -- node /absolute/path/to/mcp-server/dist/index.js # Specific repository claude mcp add git-intel -- node /absolute/path/to/mcp-server/dist/index.js /path/to/repo
Register with Any MCP Client
{
"mcpServers": {
"git-intel": {
"command": "node",
"args": ["/absolute/path/to/mcp-server/dist/index.js"],
"env": {
"GIT_INTEL_REPO": "/path/to/your/repo"
}
}
}
}
Configuration
| Priority | Method | Example |
|---|---|---|
| 1 | CLI argument | node dist/index.js /path/to/repo |
| 2 | Environment variable | GIT_INTEL_REPO=/path/to/repo |
| 3 | Current working directory | Falls back to process.cwd() |
The ~ prefix is expanded to the user's home directory in all path inputs.
Security Model
graph TD
Input["User Input<br/>tool args"] --> Zod["Zod Schema<br/>Validation"]
Zod --> PathVal["validatePathFilter()<br/>blocks .. and abs paths"]
Zod --> RefVal["validateRef()<br/>char whitelist"]
PathVal & RefVal --> ExecFile["execFile()<br/>no shell, array args"]
ExecFile --> Git["Git CLI<br/>read-only commands only"]
ExecFile --> Timeout["30s timeout"]
ExecFile --> Buffer["50MB max buffer"]
ExecFile --> Env["GIT_TERMINAL_PROMPT=0<br/>GIT_PAGER=''<br/>LC_ALL=C"]
| Threat | Mitigation |
|---|---|
| Shell injection | execFile — array args, no shell interpolation |
| Path traversal |
validatePathFilter() blocks .. and absolute paths
|
| Ref injection | validateRef() strict character whitelist |
| Write operations | Strictly read-only — no tool modifies the repository |
| Network access | No external network calls — all data is local |
| Interactive prompts | GIT_TERMINAL_PROMPT=0 |
| Timeouts | 30-second default on all git commands |
| Memory exhaustion | 50MB max buffer |
Performance
Git Command Efficiency
- Targeted
--formatstrings minimize output parsing --no-mergesskips merge commits that inflate counts--sincefilters are pushed to git (server-side filtering)- Coupling analysis caps at 50 files/commit to avoid O(n²) pair generation
- Complexity trend samples evenly (default 10 points) rather than every commit
Output Limits
- All tools accept a
limitparameter (default 20, max 50–100) - Results sorted by relevance before truncation
Concurrency
- MCP protocol handles one request at a time over stdio (serial)
- Each tool makes 1–3 sequential git calls
Deployment
graph LR
subgraph Build ["Build Pipeline"]
Code["Source Code"] --> Docker["Docker Build<br/>Multi-stage"]
Docker --> Image["Container Image<br/>~120MB"]
end
subgraph Registry ["Container Registry"]
Image --> ECR["AWS ECR"]
Image --> ACR["Azure ACR"]
end
subgraph Orchestration ["Orchestration"]
ECR --> EKS["AWS EKS<br/>Kubernetes"]
ACR --> AKS["Azure AKS<br/>Kubernetes"]
end
subgraph IaC ["Infrastructure as Code"]
TF["Terraform"] --> EKS
TF --> AKS
end
The project includes production-ready infrastructure code for both AWS and Azure. See the Infrastructure section for details.
Docker
# Build the image docker build -t mcp-git-intel:latest . # Run against a local repo docker run --rm -v /path/to/repo:/repo mcp-git-intel:latest # Docker Compose (with health checks, resource limits) docker compose up
Infrastructure
graph TD
subgraph TerraformRoot ["Terraform"]
TFMain["terraform/<br/>main.tf, variables.tf"]
TFModules["modules/<br/>networking, eks, aks"]
end
subgraph AWS ["AWS Stack"]
VPC["VPC + Subnets"]
ECR["ECR Repository"]
EKS["EKS Cluster"]
IAM["IAM Roles"]
VPC --> EKS
ECR --> EKS
IAM --> EKS
end
subgraph Azure ["Azure Stack"]
RG["Resource Group"]
VNET["VNet + Subnets"]
ACR["ACR Registry"]
AKS["AKS Cluster"]
RG --> VNET --> AKS
RG --> ACR --> AKS
end
subgraph K8s ["Kubernetes Manifests"]
NS["Namespace"]
Deploy["Deployment"]
SVC["Service"]
HPA["HPA"]
PDB["PodDisruptionBudget"]
NP["NetworkPolicy"]
SA["ServiceAccount"]
end
TFMain --> AWS
TFMain --> Azure
AWS --> K8s
Azure --> K8s
Directory Structure
aws/
cloudformation/
ecr.yaml # ECR repository
vpc.yaml # VPC, subnets, NAT
eks.yaml # EKS cluster + node group
azure/
arm/
acr.json # Container registry
vnet.json # Virtual network
aks.json # AKS cluster
terraform/
main.tf # Root module
variables.tf # Input variables
outputs.tf # Outputs
providers.tf # Provider config
environments/
dev.tfvars # Dev overrides
staging.tfvars # Staging overrides
prod.tfvars # Production config
modules/
networking/ # VPC/VNet
eks/ # AWS EKS
aks/ # Azure AKS
k8s/
base/
namespace.yaml
deployment.yaml
service.yaml
hpa.yaml
pdb.yaml
networkpolicy.yaml
serviceaccount.yaml
configmap.yaml
overlays/
dev/
staging/
prod/
Development Workflow
npm run dev # Run server with tsx (auto-reload) npm run cli # Interactive REPL for testing npm run smoke # Smoke test -- every tool and resource npm test # Unit tests (vitest) npm run test:watch # Watch mode npm run lint # Type check (tsc --noEmit) npm run build # Compile TypeScript to dist/
CLI REPL
git-intel> tools # List all tools
git-intel> resources # List all resources
git-intel> call hotspots {"days": 60} # Call a tool
git-intel> read git://repo/summary # Read a resource
git-intel> exit
Testing
graph LR
Unit["Unit Tests<br/>vitest"] --> Scoring["scoring.ts"]
Unit --> Parsing["parser.ts"]
Unit --> Formatting["formatting.ts"]
Smoke["Smoke Test"] --> AllTools["All 8 tools"]
Smoke --> AllResources["All 2 resources"]
CLI["CLI REPL"] --> AdHoc["Ad-hoc testing"]
-
Unit tests (
npm test): Vitest tests for scoring, parsing, formatting -
Smoke test (
npm run smoke): Connects a real MCP client, calls every tool and resource -
CLI REPL (
npm run cli): Interactive testing during development
Design Decisions
Formatted Text Output (not JSON)
Tools return pre-formatted text with markdown tables, score bars, and interpretation sections. AI clients can present output directly without additional formatting. JSON would require the AI to format it, adding latency and errors.
Per-Tool Git Commands (not shared cache)
Each tool makes its own git calls. Tools need different git output formats. Caching would add complexity and memory pressure. Git's pack format makes re-reading fast.
Zod for Input Validation
The MCP SDK uses Zod for schema definition, providing runtime validation and TypeScript type inference. Every parameter has a default value, so tools work with zero arguments.
Coupling Uses min() Denominator
coupling = shared / min(commitsA, commitsB) captures the "B depends on A"
relationship. If B changed 5 times and always with A, coupling is 1.0 even if A changes
independently.
Knowledge Score Weights Recency at 40%
30% volume + 30% frequency + 40% recency. Deliberately over-weights recency because code understanding decays. Recent contributors know the current state better.
Project Structure
src/
index.ts Entry point, server setup, tool/resource registration
cli.ts Interactive REPL for testing
smoke-test.ts Automated smoke test
git/
executor.ts Safe git command runner (execFile, timeouts, env)
parser.ts Git output parsers (log, numstat, conventional commits)
repo.ts Repo validation, path/ref sanitization
tools/
hotspots.ts Change frequency analysis
churn.ts Code churn (additions vs deletions)
coupling.ts Temporal coupling detection
knowledge-map.ts Knowledge scoring per author
complexity.ts Complexity trend over time
risk.ts Multi-factor risk assessment
release-notes.ts Changelog from conventional commits
contributors.ts Contributor analytics and collaboration
resources/
summary.ts Repository snapshot resource
activity.ts Recent commit activity feed
util/
scoring.ts Normalization, recency decay, coupling, risk scoring
formatting.ts Tables, score bars, text output helpers