内容
# ArchMetrics MCP
> 使 Java 项目的架构对你的编码助手可见。
ArchMetrics 是一个本地的 [模型上下文协议(MCP)](https://modelcontextprotocol.io/) 服务器,它分析编译后的 Java 字节码,并将架构结构转化为可读的报告。它衡量包稳定性、表面耦合、检测依赖循环,并检查常见的六边形架构边界——无需对被分析的项目进行任何更改。
它专为 Claude Code 和其他支持本地 `stdio` 服务器的 MCP 客户端而设计。
## 它能为你展示什么
- **主序列指标** — 抽象性、不稳定性、传入/传出耦合以及与理想序列的距离。
- **包健康状况一览** — 每个包按架构风险排名,并分为疼痛区、无用区或主序列。
- **六边形架构适应性** — 基于约定的领域、端口和适配器检测,带有隔离、纯度和具体性评分。
- **边界违规** — 导致 `DOMAIN → ADAPTER` 和 `PORT → ADAPTER` 依赖的确切类。
- **耦合详情** — 分类后的传入和传出依赖项,用于选定的包。
- **模块拓扑** — 核心/外围分类、传播成本、循环、无环性和 ASCII 依赖结构矩阵。
ArchMetrics 使用 [ASM](https://asm.ow2.io/) 读取 `.class` 文件,因此它从编译结果中看到依赖关系,而不是试图从源文本中推断它们。
## 要求
- Java 21 或更新版本
- Maven
- 编译到标准 Maven 输出目录的 Java 项目,`target/classes/`
- 带有 `stdio` 服务器支持的 MCP 客户端
## 快速入门
### 1. 构建 ArchMetrics
```bash
git clone https://github.com/baokhang83/arch-metrics-mcp.git
cd arch-metrics-mcp
mvn clean package
```
这会创建一个自包含的可执行 JAR:
```text
target/arch-metrics-1.0-SNAPSHOT.jar
```
### 2. 编译要分析的项目
```bash
cd /path/to/your/java-project
mvn compile
```
ArchMetrics 希望编译后的类位于:
```text
/path/to/your/java-project/target/classes/
```
### 3. 注册 MCP 服务器
将以下服务器定义添加到你的 MCP 客户端配置中。对于这个项目使用的 Claude Code 设置,请将其放在被分析项目中的 `.claude/mcp.json` 中:
```json
{
"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"
}
}
}
}
```
使用绝对路径,以便服务器不依赖于 MCP 客户端的工作目录。如果省略 `PROJECT_ROOT`,ArchMetrics 将分析其当前工作目录。
### 4. 请求你的助手
例如:
```text
分析所有包并解释三个最令人担忧的结果。
```
```text
查找任何六边形架构边界违规并建议如何修复它们。
```
```text
分析深度为 2 的模块并解释依赖矩阵中的循环。
```
## MCP 工具
| 工具 | 输入 | 返回内容 |
| --- | --- | --- |
| `analyze_all_packages` | 无 | 按风险排名的每个包的表格,包含检测到的层、`Nc`、`A`、`I`、`D` 和主序列区。 |
| `analyze_package` | `package_name` | 一个包的详细主序列指标和 `.stats/` 下的带时间戳的 JSON 快照。 |
| `show_coupling` | `package_name` | 完整的 `Ce` 和 `Ca` 包列表,标记为框架、领域、端口、适配器、内部或外部。 |
| `analyze_hexagonal` | 无 | 按层级的指标、架构问题、边界违规和整体六边形架构得分。 |
| `find_boundary_violations` | 无 | 每个无效的内部到外部依赖边和导致它的类。 |
| `analyze_modules` | 可选 `depth` 从 `1` 到 `4` | 逻辑模块、核心/外围区域、传播成本、循环、无环性和依赖结构矩阵。 |
示例工具参数:
```json
{
"package_name": "com.example.order.application"
}
```
```json
{
"depth": 2
}
```
## 指标
### 包指标
ArchMetrics 使用 Robert C. Martin 的包指标:
| 指标 | 含义 |
| --- | --- |
| `Nc` | 包中的类和接口数量。 |
| `Na` | 抽象类和接口的数量。 |
| `A = Na / Nc` | 抽象性。`0` 是完全具体的;`1` 是完全抽象的。 |
| `Ce` | 传出耦合:此包依赖的不同包。 |
| `Ca` | 传入耦合:依赖此包的不同项目包。 |
| `I = Ce / (Ca + Ce)` | 不稳定性。`0` 是最大稳定的;`1` 是最大不稳定的。 |
| `D = \|A + I - 1\|` | 与主序列的距离。`0` 是理想的;`1` 是最大偏差。 |
包然后被分为三个区域:
| 区域 | 规则 | 解释 |
| --- | --- | --- |
| 疼痛区 | `A < 0.5` 和 `I < 0.5` | 具体且稳定;更改对依赖项来说很昂贵。 |
| 无用区 | `A > 0.5` 和 `I > 0.5` | 抽象且不稳定;抽象可能价值不大。 |
| 主序列 | 其他所有情况 | 抽象性和稳定性的更健康的平衡。 |
### 六边形架构得分
包通过匹配单个包名称段来分类。匹配不区分大小写,并使用优先级 `ADAPTER → PORT → DOMAIN → UNKNOWN`。
| 层级 | 识别的包段 |
| --- | --- |
| 领域 | `domain`、`core`、`entity`、`entities`、`business`、`model` |
| 端口 | `port`、`ports`、`usecase`、`usecases`、`application`、`api`、`inbound`、`outbound` |
| 适配器 | `adapter`、`adapters`、`infrastructure`、`infra`、`persistence`、`repository`、`repositories`、`rest`、`web`、`http`、`controller`、`controllers`、`messaging`、`kafka`、`rabbitmq`、`amqp`、`jms`、`config`、`configuration`、`external`、`client`、`clients` |
架构报告包括:
- **领域隔离得分(DIS):** 领域依赖不指向适配器包或已知基础设施库的比例。
- **端口纯度:** 端口包的平均抽象性。
- **适配器具体性:** 适配器包的平均具体性(`1 - A`)。
- **整体六边形得分:** `DIS × 0.40 + Port Purity × 0.30 + Violation Freeness × 0.30`。
边界检查器报告项目内部的 `DOMAIN → ADAPTER` 和 `PORT → ADAPTER` 边。来自领域包到识别的外部基础设施库的依赖也降低了领域隔离得分。
### 模块指标
`analyze_modules` 找到项目共享的最长包前缀,然后使用请求的段数对包进行分组。
例如,使用常见的前缀 `com.example`:
| 包 | `depth: 1` | `depth: 2` |
| --- | --- | --- |
| `com.example.infrastructure.rest` | `infrastructure` | `infrastructure.rest` |
| `com.example.infrastructure.persistence` | `infrastructure` | `infrastructure.persistence` |
每个模块被分类为 `CORE`、`SHARED`、`PERIPHERAL` 或 `ISOLATED`,根据其传入和传出耦合。传播成本是模块可传递到达的模块的比例,包括其自身。
## 抑制已知包区警告
一些包由于设计原因而具体或高度耦合——例如生成的 DTO、配置包或应用程序入口点。将 `.arch-metrics.yml` 添加到被分析项目的根目录,以保持这些包可见而不标记其主序列区:
```yaml
suppress_zones:
- package: com.example.api.model
reason: 生成的 OpenAPI DTOs 按设计具体
- package: com.example.config
reason: 配置类故意连接应用程序
```
包值使用前缀匹配,因此抑制 `com.example.api.model` 也抑制其子包。抑制影响 `analyze_all_packages`;它们不会从分析中删除包或隐藏边界违规。
## 快照
每次 `analyze_package` 调用都会向被分析的项目写入带时间戳的 JSON 结果:
```text
.stats/
└── com.example.order.application/
└── 20260717_084300_123.json
```
这些快照可以提交或由 CI 处理,以跟踪随时间推移的架构漂移。
## 工作原理
1. MCP 客户端通过 `stdio` 启动 ArchMetrics 作为本地 Java 进程。
2. ArchMetrics 使用 ASM 扫描 `${PROJECT_ROOT}/target/classes` 下的 `.class` 文件。
3. 字节码引用聚合到包和模块依赖图。
4. 针对特定工具的指标和违规行为作为可读的 MCP 文本结果返回。
标准输出保留用于 MCP 的 JSON-RPC 传输。诊断和格式化报告写入标准错误,因此日志记录不会破坏协议流。
## 限制
- 只有 `target/classes/` 下编译的类会被分析;在源代码更改后运行 `mvn compile`。
- 层级检测基于约定。未匹配识别段的包被报告为 `UNKNOWN`。
- 反射、运行时依赖注入、服务发现和仅配置关系可能不会出现在字节码引用中。
- `target/classes/` 中的生成和合成类包含在结果中。
- 当前布局针对 Maven 样式的 Java 项目;替代构建输出目录不可配置。
## 开发
使用以下命令构建和验证服务器:
```bash
mvn clean verify
```
在测试 MCP 传输集成时直接运行它:
```bash
PROJECT_ROOT=/path/to/project java -jar target/arch-metrics-1.0-SNAPSHOT.jar
```
该进程在监听标准输入上的 MCP JSON-RPC 消息时故意保持运行。