GitIntel

Git Intelligence MCP Server — deep repository analytics computed locally from your commit history. No external APIs, no data leaves your machine.

TypeScript 5.7 Node.js ≥18 MCP SDK 1.27 Zod 3.24 Vitest 3.0 Git ≥2.20 MIT License

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
Interpretation: Files with high change frequency are candidates for refactoring, better test coverage, or breaking into smaller modules. Files changed by many authors may indicate unclear ownership.

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
Churn ratio near 1.0 means code is being rewritten as fast as it's written. Investigate root cause: unstable requirements? Wrong abstraction? Hard problem?

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
Coupling formula: 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

bash
git clone <repo-url>
cd mcp-server
npm install
npm run build

Register with Claude Code

bash
# 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

json
{
  "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 --format strings minimize output parsing
  • --no-merges skips merge commits that inflate counts
  • --since filters 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 limit parameter (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

bash
# 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

text
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

bash
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

text
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

text
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