MCP JDWP检查员
MCP(模型上下文协议)服务器,用于检查和 控制 使用JDI(Java调试接口)通过JDWP实现实时Java应用程序。
允许Claude Code在运行时检查JVM的状态,并控制执行(恢复、完成、进入、退出)。
建筑
Claude Code
↓ (MCP Protocol via STDIO)
Spring Boot MCP Server (21 tools)
↓ (JDI - Java Debug Interface)
JDWP Protocol
↓
debuggerX Proxy (port DEBUGGERX_PROXY_PORT=55005)
↓
Tomcat/Application Java (port JVM_JDWP_PORT=61959)可配置的端口:
JVM_JDWP_PORT(默认值:61959)-JVM的JDWP端口DEBUGGERX_PROXY_PORT(默认值:55005)-代理端口(IntelliJ+MCP检查器)
注: DebuggerX是一个代理,允许多个调试器同时连接。看 lib/debuggerX-README.md 更多详情。
功能
✅ 全面检查
- 具有状态的线程列表
- 完整的堆栈轨迹
- 每个帧的局部变量
- 具有递归导航的对象字段
✅ 收藏智能
- 针对ArrayList、LinkedHashMap、HashSet优化的视图
- 显示内容(元素、输入键=值)
- 表中的导航
✅ 执行控制
- 恢复/暂停线程
- 跨过、走进、走出
- 断点设置(设置/清除/列表)
- 通过IA完全控制调试器
✅ 事件监控
- 实时捕获所有JDWP事件
- 断点检测(即使是IntelliJ设置的断点)
- 监控线程中的步骤、异常、修改
- 过去100个事件的历史
✅ 表达式评估(观察者)
- 断点处任意Java表达式的评估
- 具有完整类路径的动态编译(571个条目)
- 支持字符串、原语、对象和方法
- 缓存反编译性能
- 自动代理管理(GUICE、CGLIB)
先决条件
- JDK 17+ (与
tools.jar对于JDI) - Gradle 8.11+ (包括包装)
- 应用程序Java en模式调试JDWP
安装
1.项目建设
cd mcp-jdwp-java
./gradlew.bat build这创建了: build/libs/mcp-jdwp-java-1.0.0.jar (23 MB)
2.配置克劳德代码
在 .mcp.json (在项目的根源):
{
"mcpServers": {
"jdwp-inspector": {
"command": "java",
"args": [
"-DHOME=C:/Users/nicolasv/MCP_servers/mcp-jdwp-java",
"-DJVM_JDWP_PORT=61959",
"-DDEBUGGERX_PROXY_PORT=55005",
"-jar",
"C:/Users/nicolasv/MCP_servers/mcp-jdwp-java/build/libs/mcp-jdwp-java-1.0.0.jar"
]
}
}
}可配置参数:
-DHOME:mcp jdwp java文件夹的路径(必填)-DJVM_JDWP_PORT:JVM侦听的端口(默认值:61959)-DDEBUGGERX_PROXY_PORT:debuggerX代理端口(默认值:55005)
注: 异常捕获(捕获/未捕获)和过滤器通过工具动态配置 jdwp_configure_exception_monitoring.
3.重新启动Claude代码
以便考虑新的MCP配置。
使用
步骤1:在启用JDWP的运行模式下启动Java应用程序
IntelliJ中的Tomcat示例:
Lancer启动模式 跑 (未调试)使用以下VM选项:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:61959应用程序正常启动并监听端口 JVM_JDWP_PORT=61959.
步骤2:连接IntelliJ远程调试(可选)
远程调试配置sur localhost:55005 (港口 DEBUGGERX_PROXY_PORT)
这允许通过IntelliJ放置断点,同时通过Claude代码进行检查。
注: debuggerX(le代理JDWP)服务器 自动 在第一次连接期间。
步骤3:在Claude代码中使用MCP JDWP检查器
Moi: "Connecte-toi à l'inspector"
Claude: jdwp_connect()
→ Lance debuggerX automatiquement si nécessaire
→ Se connecte au JDWP sur localhost:55005 (depuis la config .mcp.json)
→ Prêt à inspecter !
Moi: "J'ai un breakpoint actif, peux-tu analyser la requête?"
Claude:
1. Liste les threads
2. Trouve le thread suspendu
3. Inspecte la stack
4. Récupère les variables locales
5. Navigue dans les objets
6. Appelle des méthodes pour plus d'infos
7. Analyse le problèmeDebuggerX允许多个调试器(IntelliJ+MCP Inspector)同时连接。
有关多调试器路由如何工作的更多详细信息,请参阅 lib/debuggerX-README.md.
MCP工具可用(30)
1. jdwp_connect
使用配置连接到JDWP服务器 .mcp.json.
设置 : 无(自动使用中配置的端口 .mcp.json)
行为:
- 自动读取
DEBUGGERX_PROXY_PORT从系统属性 - 连接到
localhost在配置的端口上(默认值:55005) - 如果需要,自动启动DebuggerX
示例:
jdwp_connect()2. jdwp_disconnect
断开与JDWP服务器的连接。
注: 不要杀死debuggerX,只需清除本地引用。
3. jdwp_get_version
获取有关连接的JVM的信息。
返回:
VM: OpenJDK 64-Bit Server VM
Version: 11.0.21
Description: Java Debug Interface...4. jdwp_get_threads
列出所有JVM线程及其状态。
返回: 对于每个线程:
- ID唯一
- 诺姆
- 法规(1=运行,4=等待等)
- Suspendu(真/假)
- 帧数(如果暂停)
输出示例:
Found 42 threads:
Thread 0:
ID: 1
Name: main
Status: 1
Suspended: true
Frames: 14
Thread 14:
ID: 15
Name: http-nio-8080-exec-1
Status: 1
Suspended: true
Frames: 93 ← Thread avec breakpoint actif5. jdwp_get_stack
获取线程的完整调用堆栈(必须挂起)。
设置 :
threadId(long):线程ID(通过get-threads获取)
示例:
jdwp_get_stack(threadId=15)返回:
Stack trace for thread 15 (http-nio-8080-exec-1) - 93 frames:
Frame 0:
at com.axelor.web.service.RestService.find(RestService.java:186)
Frame 1:
at com.axelor.web.service.RestService$$EnhancerByGuice...
...6. jdwp_get_locals
获取特定帧的局部变量。
设置 :
threadId(长):ID du线程frameIndex(int):帧索引(0=帧库,1=调用者等)
示例:
jdwp_get_locals(threadId=15, frameIndex=0)返回:
Local variables in frame 0:
request (com.axelor.rpc.Request) = Object#26886 (com.axelor.rpc.Request)所有对象都会自动缓存以供以后检查。
7. jdwp_get_fields
获取对象的字段(或集合/数组的元素)。
设置 :
objectId(long):对象ID(通过get-locals或get-fields获取)
示例:
jdwp_get_fields(objectId=26886) # request object返回对象:
Object #26886 (com.axelor.rpc.Request):
int limit = 40
int offset = 0
java.util.List sortBy = Object#26935 (java.util.ArrayList)
java.util.Map data = Object#26936 (java.util.LinkedHashMap)
...返回ArrayList:
Object #26935 (java.util.ArrayList):
Size: 1
Elements:
[0] = "-invoiceDate"
--- Internal fields ---
...返回linkedhashmap:
Object #26936 (java.util.LinkedHashMap):
Size: 5
Entries:
"_domain" = "self.operationTypeSelect = 3"
"_domainContext" = Object#26951 (LinkedHashMap)
"operator" = "and"
"criteria" = Object#26959 (ArrayList)
...返回一个数组:
Array #26944 (java.lang.Object[]) - 10 elements:
[0] = "-invoiceDate"
[1] = null
[2] = null
...支持的集合:
ArrayList,LinkedListHashMap,LinkedHashMap,TreeMapHashSet,TreeSet- 数组(对象\[\]、int\[\]等)
9. jdwp_resume
恢复VM中所有线程的执行。
设置 : 无
示例:
jdwp_resume()返回:
All threads resumed注: 恢复所有线程,相当于IntelliJ中的f8/resume。
12. jdwp_step_over
运行当前行并在下一行停止(步骤结束,相当于F6)。
设置 :
threadId(长):线程ID(必须挂起)
示例:
jdwp_step_over(threadId=25)返回:
Step over executed on thread 25 (http-nio-8080-exec-10)注: 线程必须暂停。创建StepRequest并恢复线程。
13. jdwp_step_into
输入方法调用(步骤INTO,相当于F7)。
设置 :
threadId(长):线程ID(必须挂起)
示例:
jdwp_step_into(threadId=25)返回:
Step into executed on thread 25 (http-nio-8080-exec-10)14. jdwp_step_out
退出当前方法(步骤退出,相当于Shift+F8)。
设置 :
threadId(长):线程ID(必须挂起)
示例:
jdwp_step_out(threadId=25)返回:
Step out executed on thread 25 (http-nio-8080-exec-10)15. jdwp_set_breakpoint
在类中的特定行上放置断点。
设置 :
className(字符串):类的完整名称(例如:“com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto”)lineNumber(INT):行号
示例:
jdwp_set_breakpoint(
className="com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto",
lineNumber=82
)返回:
Breakpoint set at com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto:82注: 类必须使用debug(-g)信息加载和编译。
16. jdwp_clear_breakpoint
从特定行中删除断点。
设置 :
className(字符串):类的全名lineNumber(INT):行号
示例:
jdwp_clear_breakpoint(
className="com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto",
lineNumber=82
)返回:
Removed 1 breakpoint(s) at com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto:8217. jdwp_list_breakpoints
列出所有活动断点。
设置 : 无
示例:
jdwp_list_breakpoints()返回:
Active breakpoints: 2
Breakpoint 1:
Class: com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto
Method: save
Line: 82
Enabled: true
Breakpoint 2:
Class: com.axelor.meta.MetaFiles
Method: attach
Line: 597
Enabled: true18. jdwp_get_events
获取最近的JDWP事件(断点、步骤、异常等)。
设置 :
count(整数,可选):要检索的事件数(默认值:全部)
示例:
jdwp_get_events() # Tous les événements
jdwp_get_events(count=10) # Les 10 derniers返回:
Recent JDWP events (10):
[21:45:32] BREAKPOINT: Thread 25 at com.axelor.apps.vpauto.repository.DMSFileRepositoryVPAuto.save:74
[21:45:28] STEP: Thread 25 at com.axelor.web.service.RestService.find:186
[21:45:20] BREAKPOINT: Thread 23 at com.axelor.meta.MetaFiles.attach:597注: 事件监听器在后台运行并捕获 桃丝 JDWP事件,包括由IntelliJ或通过DebuggerX连接的其他调试器触发的事件。
捕获的事件类型:
BREAKPOINT:线程在断点停止STEP:完成/进入/退出EXCEPTION:放弃例外THREAD_START/DEATH:创建/销毁线程CLASS_PREPARE:负载类METHOD_ENTRY/EXIT:方法输入/输出(如果配置)
19. jdwp_clear_events
清除JDWP事件历史记录。
设置 : 无
示例:
jdwp_clear_events()返回:
Event history cleared注: 用于在调试会话后清理历史记录或关注新事件。
20. jdwp_get_current_thread
从代理获取当前断点的线程ID。
设置 : 无
示例:
jdwp_get_current_thread()返回:
Current thread: http-nio-8080-exec-6 (ID=26456, suspended=true, frames=93)注: 使用DebuggerX代理的HTTP API自动获取上次断点命中的线程。打电话前非常有用 jdwp_inspect_stack().
22. jdwp_get_exception_config
获取当前异常监控配置。
设置 : 无
返回:
Exception monitoring configuration:
- Capture caught exceptions: true
- Include packages: com.axelor,org.myapp
- Exclude classes: java.lang.NumberFormatException23. jdwp_clear_all_breakpoints
删除所有客户端(IntelliJ、MCP等)的所有断点。
设置 : 无
警告: 此命令还将删除IntelliJ断点!
24. jdwp_attach_watcher
将观察者附加到断点以评估Java表达式。
设置 :
breakpointId(int):断点ID(deposis)jdwp_list_breakpoints)label(String):描述du watcherexpression(字符串):要计算的Java表达式(例如:request.getData())
示例:
jdwp_attach_watcher(
breakpointId=27,
label="Trace request data",
expression="request.getData()"
)返回:
✓ Watcher attached successfully
Watcher ID: 47e8090c-dc4a-4b03-a93a-068cd1b1e1ec
Label: Trace request data
Breakpoint: 27
Expression: request.getData()25. jdwp_evaluate_watchers
评估连接到断点的观察者的表达式。
设置 :
threadId(长):ID du线吊scope(字符串):"current_frame"哦"full_stack"breakpointId(整数,可选):用于优化的断点ID
示例:
jdwp_evaluate_watchers(
threadId=26162,
scope="current_frame",
breakpointId=27
)返回:
=== Watcher Evaluation for Thread 26162 ===
─── Current Frame #0: RestService:192 (Breakpoint ID: 27) ───
• [47e8090c] Trace request data
request.getData() = Object#33761 (java.util.LinkedHashMap)
• [82632e7d] Test string
"Hello World" = "Hello World"
Total: Evaluated 2 expression(s)结果格式:
- 字符串:
"valeur" - 原语:
42,true - 对象:
Object#ID (type)
完整文档:见 表达_估价.md
26. jdwp_detach_watcher
将观察者从断点上拆下。
设置 :
watcherId(字符串):观察者的UUID(返回jdwp_attach_watcher)
示例:
jdwp_detach_watcher(watcherId="47e8090c-dc4a-4b03-a93a-068cd1b1e1ec")27. jdwp_list_watchers_for_breakpoint
列出连接到特定断点的所有观察者。
设置 :
breakpointId(int):断点ID
28. jdwp_list_all_watchers
列出所有断点上的所有活动观察者。
设置 : 无
返回:
Active watchers: 3
Breakpoint 27 (RestService:192) - 2 watcher(s):
• [47e8090c] Trace request data
Expression: request.getData()
• [82632e7d] Test string
Expression: "Hello World"
Breakpoint 29 (AuctionService:45) - 1 watcher(s):
• [9f3c2a1b] Check auction status
Expression: auction.getStatus()29. jdwp_clear_all_watchers
从所有断点中删除所有观察者。
设置 : 无
30. jdwp_inspect_stack 🚀
_(以上已记录为工具21)_
典型工作流
场景1:调试REST请求
1. Dans IntelliJ: Mettre un breakpoint dans RestService.find()
2. Dans le navigateur/Postman: Déclencher la requête
3. Dans Claude Code:
"J'ai un breakpoint actif, peux-tu analyser la requête?"
4. Claude utilise automatiquement:
- jdwp_connect() → connexion automatique avec config .mcp.json
- jdwp_get_threads() → trouve thread 15 suspendu
- jdwp_get_stack(15) → voit la stack complète
- jdwp_get_locals(15, 0) → trouve request = Object#26886
- jdwp_get_fields(26886) → voit request.data, request.limit, etc.
- jdwp_get_fields(26936) → descend dans le LinkedHashMap
"Le problème est que request.model est null alors que..."场景2:IntelliJ断点监控
1. Dans IntelliJ: Placer un breakpoint
2. Dans le navigateur: Déclencher une requête
3. IntelliJ s'arrête au breakpoint
4. Dans Claude Code:
"Est-ce que tu as détecté le breakpoint?"
5. Claude utilise:
- jdwp_get_events(count=5) → voit les derniers événements
"[21:45:32] BREAKPOINT: Thread 25 at DMSFileRepositoryVPAuto.save:74"
- jdwp_get_stack(25) → analyse la stack du thread arrêté
- jdwp_get_locals(25, 0) → inspecte les variables
"Oui, le thread 25 est arrêté à DMSFileRepositoryVPAuto.save:74
Je vois que la variable 'key' contient..."注: 事件监听器允许Claude Code“查看”IntelliJ中发生的情况,在IDE和AI之间创建协作调试体验。
项目结构
mcp-jdwp-java/
├── build.gradle # Configuration Gradle
├── settings.gradle # Modules Gradle
├── gradle.properties # Propriétés Gradle
├── gradlew.bat # Gradle wrapper (Windows)
├── .gitignore
├── README.md # Documentation principale
├── WORKFLOW.md # Guide de développement et debugging
├── EXPRESSION_EVALUATION.md # Documentation des watchers et évaluation
├── check-status.bat # Script de diagnostic
│
├── lib/
│ ├── debuggerX.jar # Proxy JDWP multi-debugger
│ └── debuggerX-README.md # Documentation du proxy
│
├── src/main/
│ ├── java/io/mcp/jdwp/
│ │ ├── JDWPMcpServerApplication.java # Main Spring Boot
│ │ ├── JDWPTools.java # 21 outils MCP exposés
│ │ ├── JDIConnectionService.java # Connexion JDWP persistante
│ │ ├── DebuggerXManager.java # Gestion automatique du proxy
│ │ │
│ │ ├── watchers/
│ │ │ ├── WatcherManager.java # Gestion des watchers
│ │ │ └── Watcher.java # Modèle de watcher
│ │ │
│ │ └── evaluation/
│ │ ├── JdiExpressionEvaluator.java # Évaluation d'expressions Java
│ │ ├── RemoteCodeExecutor.java # Exécution dans la JVM cible
│ │ ├── InMemoryJavaCompiler.java # Compilation dynamique (ECJ)
│ │ ├── ClasspathDiscoverer.java # Découverte du classpath
│ │ ├── JdkDiscoveryService.java # Détection JDK local compatible
│ │ └── exceptions/
│ │ └── JdiEvaluationException.java
│ │
│ └── resources/
│ ├── application.properties # Config Spring Boot
│ └── logback-spring.xml # Configuration des logs
│
└── build/
└── libs/
└── mcp-jdwp-java-1.0.0.jar # JAR final (23 MB)依赖性
- 弹簧靴3.4.1 -框架
- 春季AI MCP 1.1.0-M3 -MCP集成
- MCP注释0.1.0 -@McpTool
- JDI (来自tools.jar的com.sun.jdi)-调试Java接口
- Eclipse JDT编译器(ECJ)3.33.0 -表达式的动态编译
- 龙目 -注释(@slf4j用于日志记录)
- 杰克逊 -解析JSON pour API调试程序X
优势
✅ vs Python实现:
- 无JDWP手动解析
- 稳定和文档化API(JDI)
- 打字强,错误少
- 性能原生Java
✅ vs调试器经典:
- 人工智能自动检查
- 对象中的智能导航
- 问题的背景分析
- 无需手动导航
故障排除
“未找到tools.jar”
检查 JAVA_HOME 指向一个 JDK (通过JRE)。
“未找到SocketAttach连接器”
JDI不可用。将JDK与tools.jar一起使用。
连接被拒绝
- 检查Tomcat是否正在运行
-agentlib:jdwp=...address=*:61959 - 检查中的端口
.mcp.json(JVM_JDWP_PORT=61959,DEBUGGERX_PROXY_PORT=55005) - DebuggerX在连接时自动启动
MCP服务器在Claude代码中没有响应
- 重建:
./gradlew.bat build - 检查路径
.mcp.json - 重新启动Claude代码
“线程未挂起”
线程必须在断点停止,以便:
jdwp_get_stackjdwp_get_localsjdwp_invoke_method
自定义配置
转换器端口
1.修改器 .mcp.json:
{
"mcpServers": {
"jdwp-inspector": {
"command": "java",
"args": [
"-DHOME=C:/Users/nicolasv/MCP_servers/mcp-jdwp-java",
"-DJVM_JDWP_PORT=12345", // Port JVM personnalisé
"-DDEBUGGERX_PROXY_PORT=54321", // Port proxy personnalisé
"-jar",
"C:/Users/nicolasv/MCP_servers/mcp-jdwp-java/build/libs/mcp-jdwp-java-1.0.0.jar"
]
}
}
}2.更改VM应用程序选项:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:123453.重新启动Claude代码以重新加载配置
4.连接器与调试器:
- 智能J:远程调试
localhost:54321 - MCP检查员:自动使用
jdwp_connect()(照明la配置)
看 lib/debuggerX-README.md 更多详情。
版本
1.2.0 -具有Java表达式评估的完整版本
- 30 MCP工具 (8次检查+9次检查+4次事件+9名观察者)
- 表达式评估(新):
- 断点Java表达式的动态编译 - 自动类路径发现(571个条目) - 本地JDK的自动发现 - 支持动态代理(guice、cglib) - 缓存反编译性能 - 9名监督者(附加/评估/分离/列出/清除)
- 事件监控:
- 后台的事件监听器 - 捕获所有JDWP事件(即使来自IntelliJ) - 过去100个事件的历史 - 类型:断点、步骤、异常、线程等。
- 执行控制:
- 恢复/暂停线程 - 跨过/进入/退出 - 设置/清除/列出断点
- 检查:
- 无限递归导航(Remote Inspector Pattern~50倍更快) - 收藏智能 - 方法调用
- 缓存单例持久化
- DebuggerX自动启动
- 可通过以下方式配置端口
.mcp.json - 无参数连接(自动读取配置)
许可证
麻省理工学院
