内容
<img src="docs/favicon.svg" width="52" align="left" alt="the jawata arch">
# JAWATA — 编译器精确的Java分析和重构,适用于AI智能体
**智能体编写。jawata验证。Java至胜。** · [jawata.org](https://jawata.org)
[](https://github.com/haraldwegner/jawata-mcp/releases)
[](LICENSE)
[](https://openjdk.org/projects/jdk/21/)
**JAWATA让AI智能体精确地重构和维护Java代码**,具有编译器精度、行为保持和可逆性。每次更改都经过Eclipse JDT和Eclipse LTK重构引擎(与Eclipse IDE相同的机制),因此智能体编辑的是具有IDE级保证的真实代码,而不是通过文本猜测。然后,智能体将代码与编译器进行检查,可以撤销更改。正是这种精度使得**完全自主**的Java维护是安全的:在整个代码库中进行外科手术式的改进,而不会有基于文本的工具微妙错误的風險。
**为什么自主智能体可以信任它**
- **编译器精确** — 每个答案都来自Eclipse JDT的解析模型,而不是文本匹配。JAWATA *知道*您要调用哪个`save()`方法。
- **行为保持** — 重构通过LTK的前置/后置条件检查,确保语义保持不变。
- **已验证** — `compile_workspace` + `get_diagnostics` 是智能体在每次编辑后运行的真实编译器门控。
- **可逆** — 每个修改工具都返回一个`undoChangeId`;一次调用即可撤销更改。
**43个MCP工具**涵盖整个循环 — 导航、分析、重构和应用、检测代码异味(Fowler / SOLID / Kerievsky)、应用模式导向的重构、现代化、生成、管理依赖项(Maven + Gradle)、编译工作区、检测和删除重复代码。
```bash
# Linux — 安装jawata-studio,它为您获取并运行JAWATA引擎
curl -sSL https://raw.githubusercontent.com/haraldwegner/jawata-studio/main/install.sh | bash
```
JAWATA由 **[jawata-studio](https://github.com/haraldwegner/jawata-studio)** 驱动 — 桌面控制面板,下载引擎、管理工作区,并将JAWATA连接到智能体的MCP配置。macOS / Windows / 无管理器设置在 **[安装](#installation)** 部分。
---
## 为什么选择Java,现在 — 文艺复兴
二十年来,语言趋势变得简洁 — Python,然后是Kotlin、Scala、Go — 因为当时主要考虑的是*人工*创作成本。智能体时代改变了这一成本:智能体不知疲倦地编写仪式代码,JAWATA通过编译器而不是人工阅读代码库。冗长性税收现在由永不疲倦的智能体支付 — 而理解红利仍然属于您。在智能体时代,**您是审计员,而不是作者**,审计偏爱明确而非聪明;这就是为什么明确的、静态类型的Java优于简洁的Kotlin / Scala(更难审计)和动态的Python(无编译器预言)。类型不是仪式 — **它们是JAWATA赖以建立的基石**:您无法编译器精确地重构、证明行为保持或在无法静态类型代码上检测异味。**JAWATA使Java的冗长性从负债变为资产** — 让智能体*完全工程化* Java,而不仅仅是生成它。
---
## 实践中的精度
当智能体使用`grep`或纯文件读取来理解Java时,它无法区分:
- 真实的函数调用和同名函数在无关类上的调用,
- 字段读取和字段写入,
- 接口实现和其他对类型的引用,
- 强制转换和其他对该类型的提及。
结果是错误的重构、遗漏的使用和自信但不正确的推理。JAWATA驱动与Eclipse IDE相同的编译器,因此智能体获得继承、方法重载/重写、泛型、类路径+导入解析、跨包(OSGi)导航和LTK支持的重构的精确类型解析。
这里有一个更深层次的原因:**智能体的先验是寻求可验证性,而不是寻求捷径。** 它努力实现可以验证的目标 — 这在设计属性难以检查时是一种负债。使其廉价并改变先验的符号:智能体以与追求绿色测试相同的固执追求`find_field_writes = 0`。这就是编译器精确工具在智能体手中的作用 — 它将结构事实(每个字段的写入者、引用审计、SOLID和异味检测)转化为两分钟的检查,因此设计侵蚀表现为一个数字,在生产中受到监控而不是作为事件。
| 任务:查找所有调用`UserService.save()` | 结果 |
|---|---|
| `grep "save("` | 47个匹配 — 包括`orderService.save()`、 `saveButton`、注释 |
| JAWATA `find_references` | 精确的12个 — 真实的调用 |
JAWATA将此偏差与连接本身一起提供:MCP的`instructions`字段在连接时注入触发器→工具指南,因此每个客户端都被告知首先使用JAWATA — 而不是`grep`,不是手动编辑 — 用于任何语义操作([jawata-studio](https://github.com/haraldwegner/jawata-studio) 在顶部添加了一个强制先尝试的钩子)。而“理解这个符号”是一个调用:`analyze(kind=symbol)`返回定义、类型和引用,因此没有多步骤的绕路来缺陷。
### 严格的磁盘同步 — 每个答案反映当前磁盘(v2.4.0)
智能体、`git checkout`和其他编辑器都在JAWATA的JVM外部更改文件。一次工具调用前运行一次新鲜度守护进程:在毫秒级扫描中,通过证据(mtime / size,时间戳粒度窗口内的内容哈希)检测外部编辑,然后精确地协调更改的文件并重建受影响的项目 — 只有当有变化时。搜索、分析、重构更改计算和知识存储的指针判断都回答了调用时的树状结构。对于此存储库(~500个源文件,Linux,温暖)进行了测量:
| 案例 | 成本 |
|---|---|
| 未更改的树(常见情况) | ~10毫秒扫描;工具调用总计22–28毫秒 |
| 1个文件外部更改 | 下一次调用时约0.03秒(协调+重建) |
| 100个文件更改(分支切换形状) | 下一次调用时~32毫秒扫描+一次重建 |
| 新加载的项目(一次) | 整个项目的协调,~4秒 |
### 不驻留在聊天产品中的内存(v2.5.0)
聊天客户端有内存 — 不透明的:不可列出、不可导出、不可按命令写入、切换工具时消失。JAWATA的知识存储在设计上与之相反:**可移植的Markdown文件在您的git中,加上一个基于H2的存储,锚定在您的符号中。** 自v2.5.0以来,锚定是自动的 — 一个课程的文本命名其代码(`SlotManager.freeSlot`)通过编译器在摄取时解析,并锚定到它所表示的唯一真实类型;死名称、库类型和模糊名称永远不会锚定(缺失优于错误指针)。回忆是终端和分类导向的:按符号询问,获得为其编写的课程 — 带有将证据与封闭集匹配而不是发明原因的授权。由任何MCP客户端编写,由任何MCP客户端回忆:今天在Cursor中记录的课程明天在Claude Code中按符号回答。提升它、修剪它、导出它 — 它是您的。
**诚实的客户端对等性:** 工具和守护进程在每个MCP客户端上都是相同的。知识*自动推送*(会话启动、提示边界回忆、编辑时回忆)在**Claude Code上完全开启**,在**Cursor上尽力而为** — Cursor的钩子表面无法在每个缝隙中注入上下文,因此回忆的事实通过部署的规则块和在每个工具结果上骑乘的转向到达智能体。相同的知识,不同的交付 — 我们宁愿准确告诉您每个客户端获得什么也不愿声称“在任何地方都相同”。
> 智能体的先验是寻求可验证性,而不是寻求捷径 — 这在设计属性难以验证时是一种负债。使其廉价并改变先验的符号:智能体以与追求绿色测试相同的固执追求`find_field_writes = 0`。
---
## 安装
### 先决条件
- **Java 21+** 在`PATH`上 — JAWATA引擎作为JVM进程运行。
### 推荐 — 安装jawata-studio
[jawata-studio](https://github.com/haraldwegner/jawata-studio) 是桌面控制面板。它下载匹配的JAWATA引擎,管理Java项目的工作区,为每个工作区运行一个驻留的JVM,并为Cursor / Claude Desktop / Antigravity / IntelliJ样式的配置写入MCP条目。
| 平台 | 安装 |
|---|---|
| **Linux** (x86_64 / aarch64) | `curl -sSL https://raw.githubusercontent.com/haraldwegner/jawata-studio/main/install.sh \| bash` — 拉取匹配的`.AppImage`并添加桌面条目 |
| **macOS** (Apple Silicon) | 从 [jawata-studio releases](https://github.com/haraldwegner/jawata-studio/releases/latest) 下载`.dmg`(未签名 — 右键单击→打开一次以清除Gatekeeper) |
| **Windows** (x64 / ARM64) | 从 [jawata-studio releases](https://github.com/haraldwegner/jawata-studio/releases/latest) 下载`.msi`或`-setup.exe`(未签名 — 一次SmartScreen“更多信息→运行任意方式”) |
在jawata-studio窗口中添加您的Java项目(或将其自动扫描指向父文件夹),选择您的MCP客户端,它将部署配置。完成。
### 无管理器 — 自己将JAWATA连接到MCP客户端
希望直接运行引擎?下载`jawata-<platform>`存档从 [releases](https://github.com/haraldwegner/jawata-mcp/releases/latest),解压并启动:
```bash
./jawata/jawata -data /path/to/workspace-dir
```
JAWATA通过HTTP / SSE与MCP通信。启动时,它会打印一行就绪信息,包含端点和会话令牌:
```
READY url=http://127.0.0.1:8800/mcp token=ab12cd34…
```
将您的MCP客户端指向该URL(令牌在`Authorization: Bearer`头部)。对于客户端配置块:
```jsonc
{
"mcpServers": {
"jawata": {
"url": "http://127.0.0.1:8800/mcp",
"headers": { "Authorization": "Bearer ab12cd34…" }
}
}
}
```
通过编写`<data-dir>/workspace.json`定义工作区的项目(参见 [工作区工作原理](#how-workspaces-work))。jawata-studio自动化了所有这些 — 手动路径适用于自定义设置和CI。
---
## JAWATA的作用
**多项目工作区。** 一个*工作区*是一组已加载到一个JAWATA进程中的Java项目,作为一个MCP服务公开。智能体看到所有项目的组合符号集;导航、查找引用和重构在整个项目组中起作用。每个分析工具还接受一个可选的`projectKey`来限定到一个项目。
**实时更新,无需重启。** JAWATA监视`<data-dir>/workspace.json`。添加或删除项目,运行进程会在大约一秒内协调其项目列表 — 无需进程重启,无需MCP重新加载,无需智能体会话刷新。
**每种构建布局都正确解析。** Maven、Maven-Tycho、Eclipse PDE和Gradle(通过Tooling API)— 源根和依赖项按布局解析,包括OSGi `Require-Bundle`,因此跨包导航在同一工作区中的项目之间正常工作。
**行为保持重构,已应用。** 重构通过Eclipse LTK引擎运行,因此它们通过IDE强制执行的前置/后置条件检查。每个变异工具**默认应用更改**,并返回diff和`undoChangeId` — 一次调用即可撤销。重命名、提取、内联、移动、拉取/推送、封装字段和更改签名都重写整个工作区中的每个受影响的引用。
**内置验证。** `compile_workspace` + `get_diagnostics` 为智能体提供了一个真正的编译器门控,用于在继续之前检查自己的编辑。
---
## 工具
> 前门将许多操作合并在`kind`参数后面 — 例如`extract(kind)`、`inline(kind)`、`find_quality_issue(kind)`、`refactor_to_pattern(kind)` — 因此加载的表面保持较小(41),而其下的功能通过注册不断增长。
**工作区和导航**
- *工作区* — `load_project`、`project` *(列出/添加/删除)*、`refresh_workspace`
- *导航* — `go_to_definition`、`find_references` *(引用/实现/方法引用)*、`get_call_hierarchy` *(传入/传出)*、`inspect` *(类型层次结构/文档符号/类型成员/...)*、`get_at_position` *(类型/方法/字段/悬停/文档/签名/封闭/超/符号)*
- *搜索* — `search_symbols`、`find_pattern_usages` *(注解/实例化/类型参数/强制转换/ instanceof)*、`find_field_writes`
**理解**
- *分析* — `analyze` *(文件/类型/方法/控制流/数据流/影响分析/命名/ JavaDocs/空指针/符号 — 一次调用:定义+类型+引用)*,`find_quality_issue` *(质量:命名/错误/未使用/大类/循环依赖/反射/抛出/捕获 · 18种Fowler代码异味 · SOLID:dip / isp / srp_cohesion / lsp · Kerievsky:单例/类型代码 — 带有`family`过滤器:质量/ fowler / solid / kerievsky)*
- *检查* — `inspect` *(复杂度/项目结构/类路径/类型用法/依赖图/依赖注入注册)*
**更改**
- *重构* — `rename_symbol`、`extract` *(方法/变量/常量/接口/超类)*、`inline` *(方法/变量)*、`move` *(类/包)*、`move_in_hierarchy` *(拉取/推送)*、`encapsulate_field`、`change_method_signature`、`convert_anonymous_to_lambda`、`generate` *(构造函数/获取器/设置器/ equals_hashcode / tostring /测试骨架/覆盖方法/复制类)* · `refactoring` *(单个更改:应用/撤销/检查 · 多步骤,等价门控:计划/应用计划/检查计划/撤销计划)*
- *多步骤编排* — `refactoring(action=plan → apply_plan)` 将重构作为原子、行为保持的步骤进行,并带有**等价门控**(编译0/0 +纯度检查)在每一步;如果构建中断或控制流更改被走私,则整个计划会原子地回滚。`copy_class` + `extract(kind=superclass)` 是编译器编写代码的原语(复制类,然后将共享成员提升到父类)— 重用而不是重新编写。
- *重构为模式(Kerievsky)* — `refactor_to_pattern` *(内联单例/组合方法/用类替换类型代码/重构为状态/重构为命令调度器/模板方法/重构为访问者/用习语替换模式)* — 行为保持,可逆,编译;朝着复杂性保证的模式和远离过时模式。OCP治愈:`divergent_change` / `shotgun_surgery` 指向一个可运行的`refactoring(action=plan, kind=refactor_to_state | refactor_to_command_dispatcher | form_template_method)`。
- *导入和现代化* — `organize_imports`、`optimize_imports_workspace`、`find_modernization` *(8种习惯)*、`apply_cleanup` *(添加final /冗余修饰符)*
- *空安全* — `apply_null_annotations` *(添加/迁移)*
- *格式* — `format`
- *快速修复* — `quick_fix` *(建议导入/列表/应用)*、`validate_syntax`
- *重复代码* — `find_duplicate_code`、`replace_duplicates`
**构建和验证**
- *依赖项(Maven)* — `dependency` *(添加/更新/查找未使用的)*
- *验证* — `compile_workspace`、`get_diagnostics`、`find_tests`、`run_tests`
- *健康状况* — `health_check`
**学习(知识存储)**
- *经验* — `experience` *(记录/回忆/预设/加载/刷新/擦除/提升)* — 本地的工作区范围的知识存储。记录一个教训/危险/领域事实;**回忆**它为**提示**(一个合适的节点,指针解析为当前代码,或权威缺失 — 绝不相似); 在会话开始时**预设**领域层; 从内存文件**播种**并保持指针诚实。
**调试(运行中的JVM)**
- *调试* — `debug` *(发现/启动/附加/断点/等待/快照/评估/步骤/探针/重放/设置值/强制返回/弹出帧/重新定义)* — 附加到正在运行的JVM,或在第一条指令之前启动一个。 在正在运行的程序中**断开**、检查和评估(`evaluate`中的真实方法调用实际上会在那里运行); **探测**而不断开它; 声明一个**不变**并捕获它被破坏的第一刻。 命中的名称为类和方法 — 这恰好是`get_call_hierarchy`和`find_references`使用的键,因此运行时事实可以直接在编译器精确工具中使用,无需在它们之间进行搜索。
*44种工具* 总计;前门户(`analyze`、`inspect`、`extract`、`inline`、`move`、`generate`、`find_quality_issue`、`find_pattern_usages`、`find_modernization`、`refactor_to_pattern`、`dependency`、`quick_fix`、`refactoring`、`project`、`debug`)每个调度一个`kind`/操作,因此加载的表面保持较小,而功能通过注册不断增长。
## 运行时调试 — 对目标的影响
在将 `debug` 指向任何内容之前,请先阅读本节。
**1. 调试会话会暂停线程并更改其附着的JVM中的状态。** 断点会停止程序;`set_value`、`force_return`、`pop_frame` 和 `redefine` 会重写程序。这不是观察,而是干预 — 调试会话会记录它所做的每个更改,因为您编辑过的程序已经不是您最初启动的程序,从中得出的任何发现都必须说明这一点。
**2. 它适用于开发或模拟机器。** 这不是事后添加的免责声明;这是JVM的工作方式。只有在启动时添加了调试代理的JVM才能被调试,并且不能为正在运行的JVM添加调试代理 — OpenJDK的JDWP代理没有附加入口点。因此,如果生产环境中的JVM不是为调试而启动的,那么它不受我们编写的任何策略保护;它只是无法访问。危险的操作是不可表示的,而不是被拒绝的。
**3. 在JVM *可调试*的情况下 — 测试或预发布环境、共享模拟环境 — 将其指向它需要您的专业判断。** 通常的预发布流程是开发 → 测试 → 生产,在测试环境中启用调试代理对于专业人员来说是完全正常的需求。jawata 不会代替您做出判断。但是,在其他人依赖的机器上暂停线程会有后果,这些后果由您承担,而不是我们:如果您不知道停止该JVM会产生什么影响,那么这就是答案。
探针(`probe_set`)专门用于您可能 **不** 停止整个系统的情况下:它们读取JVM自己的事件,并且从不暂停任何内容。只有一个例外 — 捕获表达式的日志点必须读取一个帧,因此它会短暂地停止线程,并且报告 `perturbs: true` 而不是假装不是这样。
---
## 工作空间的工作原理
工作空间由引擎监视的JSON文件描述:
```json
{ "version": 1, "name": "example", "projects": ["/abs/path/project-a", "/abs/path/project-b"] }
```
JAWATA 加载列出的所有项目到一个进程中,并将它们作为单个MCP端点提供。`java.nio.file.WatchService` 会在大约一秒内检测到此文件的更改,并协调活动项目集。jawata-studio 在您添加和删除UI中的项目时写入并维护此文件;当独立运行管理器时,您需要自己编写。
**已知的限制 — 每个项目树只有一个 JAWATA。** 在同一时间为一个项目目录提供服务,并且在构建或其他写入器正在修改同一树时,避免通过JAWATA重构。并发访问不会无声地损坏 — 遇到干扰的操作会失败并报告错误 — 但跨进程的协调尚未提供。
---
## 配置
| 变量 | 用途 |
|---|---|
| `JAWATA_HTTP_PORT` | MCP端点的绑定端口(默认值:自动在8800–8999范围内选择) |
| `JAWATA_HTTP_TOKEN` | 客户端必须提供的会话令牌(默认值:生成,在 `READY` 中打印) |
| `JAWATA_DATA_DIR` | 工作空间数据目录(`workspace.json`的位置) |
jawata-studio 会自动为每个工作空间设置这些变量,并为每个工作空间分配一个稳定的 `(端口, 令牌)`,这样多个代理共享一个引擎,而不是为每个引擎启动一个JVM。
---
## 从源代码构建
```bash
git clone https://github.com/haraldwegner/jawata-mcp.git
cd jawata-mcp
mvn install # 普通Maven,大约10秒 — dist在build/dist/target/dist下
java -jar build/dist/target/dist/jawata.jar -data <ws> # 运行它
java -jar build/dist/target/dist/jawata.jar -runTests # 完整的测试套件,在框架内
```
需要JDK 21。从Sprint 22d开始,构建是 **普通Maven** — Eclipse的JDT/platform包直接来自Maven Central,一个小型启动模块以编程方式启动嵌入式OSGi框架(与Eclipse自己的Java语言服务器使用的模式相同)。一个通用的dist可以在所有平台上运行。
---
## 架构
JAWATA是一个基于Eclipse JDT和Eclipse语言工具包(LTK)的OSGi应用程序:
- **`org.jawata.core`** — 工作空间 + 项目模型,JDT集成,分析和重构引擎。
- **`org.jawata.mcp`** — MCP服务器:工具注册表,协议处理程序,HTTP/SSE传输。
- **`org.jawata.launcher`** / **`org.jawata.product`** — Equinox启动器和打包产品。
一个进程托管整个工作空间;工具在共享的JDT模型上运行,这使得跨项目、编译器准确的答案变得廉价。
---
## 历史和许可证
JAWATA最初是Peter Zalutski的MIT许可的 **[javalens-mcp](https://github.com/pzalutski-pixel/javalens-mcp)** 的一个分支。保留了MIT基础,并在 [`NOTICE`](NOTICE) 中予以认可。JAWATA在 **[GNU AGPL-3.0](LICENSE)** 下分发 — 在网络上运行JAWATA服务器使其成为受版权保护的作品,因此网络用户有权获取其源代码。贡献在 **[Contributor License Agreement](CLA.md)** 下接受;请参见 [`CONTRIBUTING.md`](CONTRIBUTING.md)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器