Repo Recon

MCP server · six readers for a codebase you did not write

Where to start reading, what a change would reach, and what is risky about the release. It reads the AST — never imports the code, never runs it — and its only subprocesses are git log, git rev-parse and git ls-files.

View on GitHub →

Interface

The interface
The interface
The read console
The read console

A real run

pointed it at a repository nobody here wrote

{
 "tool": "map_repo",
 "path": "<a checkout of requests>"
}

what came back

{
 "name": "requests",
 "modules": 36,
 "symbols": 753,
 "loc": 11245,
 "repo_resolution_rate": 0.5634,
 "resolution_rate_all_call_sites": 0.3019,
 "resolved_calls": "782 of 1388 in scope (2590 call sites in all)",
 "most_important_module": "requests.compat (imported by 13)",
 "most_called": "requests.api.get (fan-in 82)",
 "unresolved_sample": [
  [
   "httpbin",
   150
  ],
  [
   "s.get",
   34
  ],
  [
   "urlparse",
   23
  ],
  [
   "sock.send",
   21
  ],
  [
   "r.prepare",
   20
  ],
  [
   "close_server.set",
   15
  ],
  [
   "jar.set",
   15
  ],
  [
   "s.mount",
   13
  ],
  [
   "r.json",
   12
  ],
  [
   "s.send",
   12
  ]
 ]
}

s.get in the unresolved sample is the shape that accounts for 63% of everything this resolver cannot bind: a method on a variable whose type is stated nowhere in the file.

asked what would be affected by changing one method

{
 "tool": "trace_impact",
 "symbol": "Session.request",
 "path": "<the same checkout>"
}

what came back

{
 "resolved": "requests.sessions.Session.request",
 "total_callers": 7,
 "callers_by_depth": {
  "hop_1": [
   "requests.sessions.Session.delete",
   "requests.sessions.Session.get",
   "requests.sessions.Session.head",
   "requests.sessions.Session.options",
   "requests.sessions.Session.patch",
   "requests.sessions.Session.post",
   "requests.sessions.Session.put"
  ]
 }
}

asked what the codebase is eligible to modernise

{
 "tool": "check_modernisation",
 "path": "<the same checkout>"
}

what came back

{
 "files_scanned": 36,
 "mechanical": 0,
 "behavioural": 0,
 "rules_available": [
  "naive-now",
  "pep585-generics",
  "pep604-optional",
  "pep604-union",
  "utcfromtimestamp-deprecated",
  "utcnow-deprecated"
 ],
 "parse_errors": []
}

A null result shown as one: this codebase is already modern against all three rules. Mechanical and behavioural are counted separately and never added together, because only one of them can change what the code does.

The number this project exists to report. Run against its own repository the resolver binds 93.7% of in-scope calls. Run against twelve projects nobody here wrote - 1,063,636 lines at pinned revisions - the median is 61.5% and the worst is 38.0%. A rate measured on the code a resolver was written against is a measurement of the agreement between a tool and its own training set of one.

Captured from a real run on 2026-10-24 at revision ce1a762, against a pinned checkout of a third-party library. Nothing is edited. This page is static - the tool reads a repository on your own disk, so there is nothing for it to read here.

What it does

map_repo
Modules that matter by PageRank, entry points, and how much of the call graph resolved
trace_impact
Every definition that reaches the named one, grouped by hops
check_modernisation
Mechanical edits and behavioural ones, counted apart — never one number
review_diff
Proposes findings, then tries to disprove each and retracts what does not hold
release_readiness
Scored from the repository's own history, each check with the number behind it
riskiest_commits
Commits scored against this repository's median, not an absolute

What it will not do

It writes nothing. Set REPO_RECON_ROOT and it refuses any path that resolves outside it — including one reached through a link inside the tree — and reports what it refused rather than quietly leaving it out. A retracted finding is not a finding.

Stack