Skip to main content
Glama
tanvi0102

change-impact-assistant

by tanvi0102
README.md
# Change Impact Assistant

An MCP server that answers one question for a developer or an AI coding agent: **"I just changed this — what else might I need to check?"**

It combines two independent signals:

- **Static code structure** — reads the codebase with Python's built-in `ast` module to find which files/functions import or call each other *right now*.
- **Git co-change history** — reads the repo's commit history to find files that have changed *together* in the past, even when nothing in the code connects them.

Neither signal alone is enough: static analysis misses config files, docs, or tests that always change alongside a piece of code but never import it; history alone misses brand-new code with no track record. Combining both catches more than either does on its own.

This is a small, original Python implementation of both ideas, built from scratch and kept intentionally simple.

## Example

Given a change to `payment_service.py`:

```
HIGH CONFIDENCE
- invoice_service.py
  Reason: calls refund (changed in payment_service.py)

MEDIUM CONFIDENCE
- checkout_api.py
  Reason: imports payment_service.py, but doesn't call refund directly
- test_refunds.py
  Reason: changed together with payment_service.py in 4 of its last 6 changes (67%)

REVIEW SUGGESTED
- payment_config.yaml
  Reason: changed together with payment_service.py in 1 of its last 6 changes (17%)
```

`invoice_service.py` is HIGH because it actually calls the function that changed. `checkout_api.py` imports the file but calls a *different*, unchanged function, so it's demoted to MEDIUM rather than being blanket-flagged. `test_refunds.py` has no code connection at all — the only reason it's here is git history. `payment_config.yaml` is the same idea, weaker signal.

## Install

Requires Python 3.10+ and Git.

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

## Usage

**Command line:**
```bash
python -m impact_assistant analyze /path/to/your/repo
```
This reads `git diff` in that repo and prints the tiered report. Useful flags:
- `--against HEAD~1` — compare against a specific ref instead of the working tree vs HEAD
- `--since "1 year ago"` — limit how far back co-change history looks
- `--file some/file.py` — analyze a specific file instead of the live diff (repeatable)

**As an MCP server** (for Claude Code, Claude Desktop, or any MCP-compatible AI assistant), add to `.mcp.json`:
```json
{
  "mcpServers": {
    "change-impact-assistant": {
      "command": "/path/to/change-impact-assistant/.venv/bin/mcp",
      "args": ["run", "/path/to/change-impact-assistant/src/impact_assistant/server.py"]
    }
  }
}
```
This exposes 5 tools: `analyze_current_change`, `explain_affected_file`, `get_static_impact`, `get_historical_impact`, `get_changed_files`.

**Interactively**, with the official [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
mcp dev --with-editable . src/impact_assistant/server.py
```

## How it works

| File | Role |
|---|---|
| `codegraph.py` | Builds a static "what imports/calls what" map of the codebase using `ast`. |
| `cochange.py` | Reads `git log` and counts which files have historically changed together. |
| `symboldiff.py` | Compares old vs. new versions of a changed file to find *which specific* function/class changed, instead of treating any edit as "the whole file is different." |
| `gitdiff.py` | Wraps `git diff` to find what's currently changed. |
| `report.py` | Merges the above into one tiered, evidence-backed report — the core original logic. |
| `cli.py` | Command-line entry point. |
| `server.py` | MCP server exposing the same logic as tools an AI assistant can call directly. |

## Known simplifications (deliberate, not oversights)

- **File/function names, not full scope resolution.** Calls and imports are matched by name across the whole codebase. Two files with a same-named function can be conflated. A real type checker would resolve this exactly; this trades some precision for staying simple.
- **Change unit = one commit**, not a PR/merge-aware grouping. A history with many small fixup commits per PR will look noisier than a tool that groups by PR.
- **Top-level functions/classes only** for symbol-level diffing — a changed method inside a class shows up as "the class changed," not the specific method.
- **Python codebases only.**
- **No persistent cache** — the code graph and git history are rebuilt on every call. Fine for small/medium repos (verified under 100ms even on a ~6,500-commit, 37-file real project); would need caching for much larger ones.

## Testing

```bash
pip install -e ".[dev]"
pytest tests/
```

Tests build a small, deterministic fake project with a hand-crafted git history (see `tests/conftest.py`) so results are reproducible. The tool has also been run against a real, unrelated open-source project (`psf/requests`) during development, which surfaced and led to fixing two real bugs that a synthetic test alone didn't catch.

## License

MIT — see [LICENSE](LICENSE).

TDQS

A3.6/5.0

Scored across 5 tools

Disambiguation4/5

Most tools are clearly separated by their evidence source or scope: whole-diff analysis vs single-file explanation vs static vs historical. analyze_current_change and explain_affected_file are related but distinct enough in descriptions (whole set vs one file). Some minor overlap remains around which tool to pick for single-file impact evidence.

Naming Consistency4/5

Four tools use the get_* prefix and analyze_current_change/explain_affected_file use action_noun. The naming is clear and predictable, though there's a slight mix of get_ vs analyze_/explain_ verbs rather than a single uniform convention.

Tool Count5/5

Five tools tightly cover the change-impact domain: list changed files, analyze the whole diff, explain a single file, and query static or historical evidence. No redundancy and no bloat.

Completeness4/5

The main workflow is covered: list changed files, run a diff-based impact analysis, and drill into static or historical evidence per file. A possible minor gap is a way to combine static and historical evidence on demand outside the current-diff analysis.

Maintenance

ActivityMaintained
ResponsivenessNo issues