Dependency Doctor

Tools for resolving dependency conflicts

Documentation

dependency-doc

Listed on mcpservers.org

An MCP server that explains Maven dependency resolution. Ask your AI assistant why a version is on your classpath — and get the actual answer: which rule decided, who requested what, and the full path of the dependency that dragged it in.

You: why do I have commons-lang3 3.9 in my project?

Claude (via dependency-doc): The chain is spring-boot-testcontainers → testcontainers 2.0.5 → commons-compress 1.28.0 → commons-lang3 3.20.0 (test scope) — but Maven resolved to 3.9 anyway. Maven doesn't pick the newest version, it picks the nearest declaration in the tree, and your pom declares 3.9 directly. Your one-line declaration silently downgraded the whole project by eleven versions.

Why this exists

mvn dependency:tree -Dverbose shows you that a version was omitted. It never explains why — and the why involves rules most developers have never been taught: nearest-wins mediation, dependencyManagement pins, BOM imports, exclusion shadowing. A typical Spring Boot project inherits over 1,900 managed versions it never wrote. When an upgrade mysteriously doesn't take effect, the answer is buried in that machinery.

dependency-doc runs Maven's own resolution machinery (Maven Resolver + Model Builder) against your actual pom.xml and exposes the results as MCP tools, so an AI assistant can answer dependency questions with evidence instead of guesses.

Tools

analyzeDependencies(pomPath) — full-tree health check: node counts, direct dependencies, and every version conflict with its complete explanation.

explainVersion(pomPath, groupArtifact) — the core feature. For one library: the resolved version, the rule that decided it (direct declaration / dependencyManagement / nearest-wins), and every request with its path and outcome.

findDependencyPaths(pomPath, groupArtifact) — every chain by which a library enters your build. Useful for planning exclusions.

Setup

Requires Java 21+.

git clone https://github.com/sindhunaydu/dependency-doc.git
cd dependency-doc
./gradlew bootJar

Add to Claude Desktop's config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "dependency-doc": {
      "command": "java",
      "args": ["-jar", "/absolute/path/to/dependency-doc/build/libs/dependency-doc-0.0.1-SNAPSHOT.jar"]
    }
  }
}

Restart Claude Desktop fully, then ask it something like: "Analyze the dependencies of /path/to/my-project/pom.xml — why is jackson-databind at the version it's at?"

How it works

dependency-doc embeds the same libraries Maven itself is built on. The Model Builder turns your pom.xml into the effective model — parents inherited, BOMs imported, properties interpolated. Maven Resolver then collects the full dependency graph with conflict-loser preservation enabled, so superseded requests stay in the graph, marked with what beat them. The analysis layer walks that graph and turns markings into explanations.

Analysis differs from a build in one important way: your project's own test and provided dependencies are part of the truth (a custom scope selector encodes Maven's exact semantics — direct test deps in, other libraries' test universes out).

A note on strict mode (a debugging saga)

This tool refuses to silently omit branches. During development, a stack of quiet defaults — a lenient artifact-descriptor policy plus an empty-looking exception list — produced a confident "Conflicts: 0" on a project that verifiably had conflicts. The cause: parent poms with JDK-activated profiles failed to build when the resolver session lacked system properties, and the lenient policy swallowed every failure, leaving childless nodes and a clean-looking report.

dependency-doc therefore runs with a strict descriptor policy and surfaces every collection problem in its responses. An analysis that fails loudly is useful; one that lies confidently is worse than none. If a response includes a "⚠ Analysis incomplete" section, believe it.

Limitations & roadmap

  • Maven only, for now. Gradle resolution uses a genuinely different model (highest-wins, constraints, resolution rules) and is planned as v2 via the Gradle Tooling API.
  • Single-module projects; multi-module reactor support is planned.
  • Tree diffing (what changes if I bump X?) is on the roadmap.

Issues and PRs welcome.

License

Apache 2.0