Are you the author? Sign in to claim
๐ MCP server that analyzes Java bytecode for package stability, coupling, cycles, and Hexagonal Architecture violations
Make the architecture of a Java project visible to your coding assistant.
ArchMetrics is a local Model Context Protocol (MCP) server that analyzes compiled Java bytecode and turns architectural structure into readable reports. It measures package stability, surfaces coupling, detects dependency cycles, and checks common Hexagonal Architecture boundariesโwithout requiring changes to the project being analyzed.
It is designed for Claude Code and other MCP clients that support local stdio servers.
DOMAIN โ ADAPTER and PORT โ ADAPTER dependencies.ArchMetrics reads .class files with ASM, so it sees dependencies in the compiled result rather than trying to infer them from source text.
target/classes/stdio server supportgit clone https://github.com/baokhang83/arch-metrics-mcp.git
cd arch-metrics-mcp
mvn clean package
This creates a self-contained executable JAR:
target/arch-metrics-1.0-SNAPSHOT.jar
cd /path/to/your/java-project
mvn compile
ArchMetrics expects the compiled classes at:
/path/to/your/java-project/target/classes/
Add the following server definition to your MCP client configuration. For the Claude Code setup used by this project, place it in .claude/mcp.json inside the project being analyzed:
{
"mcpServers": {
"arch-metrics": {
"command": "java",
"args": [
"-jar",
"/absolute/path/to/arch-metrics-mcp/target/arch-metrics-1.0-SNAPSHOT.jar"
],
"env": {
"PROJECT_ROOT": "/absolute/path/to/your/java-project"
}
}
}
}
Use absolute paths so the server does not depend on the MCP client's working directory. If PROJECT_ROOT is omitted, ArchMetrics analyzes its current working directory.
For example:
Analyze all packages and explain the three most concerning results.
Find any hexagonal architecture boundary violations and suggest how to fix them.
Analyze modules at depth 2 and explain the cycles in the dependency matrix.
| Tool | Input | What it returns |
|---|---|---|
analyze_all_packages | None | A risk-ranked table of every package with its detected layer, Nc, A, I, D, and Main Sequence zone. |
analyze_package | package_name | Detailed Main Sequence metrics for one package and a timestamped JSON snapshot under .stats/. |
show_coupling | package_name | Complete Ce and Ca package lists labeled as framework, domain, port, adapter, internal, or external. |
analyze_hexagonal | None | Per-layer metrics, architecture issues, boundary violations, and aggregate Hexagonal Architecture scores. |
find_boundary_violations | None | Each invalid inner-to-outer dependency edge and the classes that cause it. |
analyze_modules | Optional depth from 1 to 4 | Logical modules, core/periphery zones, propagation costs, cycles, acyclicity, and a Dependency Structure Matrix. |
Example tool arguments:
{
"package_name": "com.example.order.application"
}
{
"depth": 2
}
ArchMetrics uses Robert C. Martin's package metrics:
| Metric | Meaning |
|---|---|
Nc | Number of classes and interfaces in the package. |
Na | Number of abstract classes and interfaces. |
A = Na / Nc | Abstractness. 0 is fully concrete; 1 is fully abstract. |
Ce | Efferent coupling: distinct packages this package depends on. |
Ca | Afferent coupling: distinct project packages that depend on this package. |
I = Ce / (Ca + Ce) | Instability. 0 is maximally stable; 1 is maximally unstable. |
D = |A + I - 1| | Distance from the Main Sequence. 0 is ideal; 1 is the maximum deviation. |
Packages are then grouped into three zones:
| Zone | Rule | Interpretation |
|---|---|---|
| Zone of Pain | A < 0.5 and I < 0.5 | Concrete and stable; changes are expensive for dependents. |
| Zone of Uselessness | A > 0.5 and I > 0.5 | Abstract and unstable; abstractions may have little value. |
| Main Sequence | Everything else | A healthier balance of abstractness and stability. |
Packages are classified by matching individual package-name segments. Matching is case-insensitive and uses the priority ADAPTER โ PORT โ DOMAIN โ UNKNOWN.
| Layer | Recognized package segments |
|---|---|
| Domain | domain, core, entity, entities, business, model |
| Port | port, ports, usecase, usecases, application, api, inbound, outbound |
| Adapter | adapter, adapters, infrastructure, infra, persistence, repository, repositories, rest, web, http, controller, controllers, messaging, kafka, rabbitmq, amqp, jms, config, configuration, external, client, clients |
The architecture report includes:
1 - A) of adapter packages.DIS ร 0.40 + Port Purity ร 0.30 + Violation Freeness ร 0.30.The boundary checker reports project-internal DOMAIN โ ADAPTER and PORT โ ADAPTER edges. Dependencies from domain packages to recognized external infrastructure libraries also reduce the Domain Isolation Score.
analyze_modules finds the longest package prefix shared by the project, then groups packages using the requested number of segments after that prefix.
For example, with the common prefix com.example:
| Package | depth: 1 | depth: 2 |
|---|---|---|
com.example.infrastructure.rest | infrastructure | infrastructure.rest |
com.example.infrastructure.persistence | infrastructure | infrastructure.persistence |
Each module is classified as CORE, SHARED, PERIPHERAL, or ISOLATED from its incoming and outgoing coupling. Propagation Cost is the fraction of modules transitively reachable from that module, including itself.
Some packages are concrete or highly coupled by designโfor example, generated DTOs, configuration packages, or application entry points. Add .arch-metrics.yml to the root of the project being analyzed to keep those packages visible without flagging their Main Sequence zone:
suppress_zones:
- package: com.example.api.model
reason: Generated OpenAPI DTOs are concrete by design
- package: com.example.config
reason: Configuration classes intentionally wire the application
Package values use prefix matching, so suppressing com.example.api.model also suppresses its subpackages. Suppressions affect analyze_all_packages; they do not remove packages from analysis or hide boundary violations.
Every analyze_package call writes a timestamped JSON result to the analyzed project:
.stats/
โโโ com.example.order.application/
โโโ 20260717_084300_123.json
These snapshots can be committed or processed by CI to track architectural drift over time.
stdio..class files below ${PROJECT_ROOT}/target/classes with ASM.Standard output is reserved for MCP's JSON-RPC transport. Diagnostics and formatted reports are written to standard error, so logging cannot corrupt the protocol stream.
target/classes/ are analyzed; run mvn compile after source changes.UNKNOWN.target/classes/ are included in the results.Build and verify the server with:
mvn clean verify
Run it directly when testing an MCP transport integration:
PROJECT_ROOT=/path/to/project java -jar target/arch-metrics-1.0-SNAPSHOT.jar
The process intentionally remains running while it listens for MCP JSON-RPC messages on standard input.
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows