mcp-jvm-diagnostics 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/analyzers/gc-pressure.js +16 -5
- package/build/index.js +4 -4
- package/package.json +2 -2
|
@@ -26,7 +26,16 @@ export function analyzeGcPressure(log) {
|
|
|
26
26
|
result.maxPauseMs = pauses[pauses.length - 1];
|
|
27
27
|
result.totalPauseMs = pauses.reduce((a, b) => a + b, 0);
|
|
28
28
|
result.avgPauseMs = result.totalPauseMs / pauses.length;
|
|
29
|
-
|
|
29
|
+
// Linear interpolation for P95: Math.floor(n * 0.95) returns index n-1 whenever
|
|
30
|
+
// n <= 20, making P95 equal the max. Using (n-1) * 0.95 as the fractional index
|
|
31
|
+
// and interpolating between adjacent elements gives accurate results at all sizes.
|
|
32
|
+
const p95Idx = (pauses.length - 1) * 0.95;
|
|
33
|
+
const p95Lo = Math.floor(p95Idx);
|
|
34
|
+
const p95Hi = Math.ceil(p95Idx);
|
|
35
|
+
result.p95PauseMs =
|
|
36
|
+
p95Lo === p95Hi
|
|
37
|
+
? pauses[p95Lo]
|
|
38
|
+
: pauses[p95Lo] + (pauses[p95Hi] - pauses[p95Lo]) * (p95Idx - p95Lo);
|
|
30
39
|
// GC overhead
|
|
31
40
|
if (log.timeSpanMs > 0) {
|
|
32
41
|
result.gcOverheadPct = (result.totalPauseMs / log.timeSpanMs) * 100;
|
|
@@ -70,8 +79,10 @@ function detectIssues(log, result) {
|
|
|
70
79
|
result.issues.push(`Heap after GC is growing over time (${avgFirst.toFixed(0)}MB → ${avgSecond.toFixed(0)}MB) — possible memory leak.`);
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
|
-
// Low reclaim ratio
|
|
74
|
-
|
|
82
|
+
// Low reclaim ratio — only meaningful when heap actually shrank after GC.
|
|
83
|
+
// Guard heapAfterMb < heapBeforeMb to avoid a negative reclaim percentage when
|
|
84
|
+
// averaged heap-after exceeds heap-before (e.g. growing heap events skewing averages).
|
|
85
|
+
if (result.heapBeforeMb > 0 && result.heapAfterMb > 0 && result.heapAfterMb < result.heapBeforeMb) {
|
|
75
86
|
const reclaimPct = ((result.heapBeforeMb - result.heapAfterMb) / result.heapBeforeMb) * 100;
|
|
76
87
|
if (reclaimPct < 10) {
|
|
77
88
|
result.issues.push(`GC reclaims only ${reclaimPct.toFixed(0)}% of heap per collection — most objects survive. Heap may be too small or there's a memory leak.`);
|
|
@@ -97,8 +108,8 @@ function generateRecommendations(log, result) {
|
|
|
97
108
|
if (fullGcCount > 3) {
|
|
98
109
|
result.recommendations.push("Frequent Full GCs indicate heap pressure. Increase -Xmx or tune -XX:InitiatingHeapOccupancyPercent (G1) to start concurrent marking earlier.");
|
|
99
110
|
}
|
|
100
|
-
// Low reclaim → check for leaks
|
|
101
|
-
if (result.heapBeforeMb > 0) {
|
|
111
|
+
// Low reclaim → check for leaks (same guard as detectIssues: skip when averages are inverted)
|
|
112
|
+
if (result.heapBeforeMb > 0 && result.heapAfterMb < result.heapBeforeMb) {
|
|
102
113
|
const reclaimPct = ((result.heapBeforeMb - result.heapAfterMb) / result.heapBeforeMb) * 100;
|
|
103
114
|
if (reclaimPct < 10) {
|
|
104
115
|
result.recommendations.push("Very low reclaim ratio suggests most objects are long-lived. Take a heap dump and analyze with Eclipse MAT or jmap -histo to identify memory leaks.");
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { parseJfrSummary } from "./parsers/jfr-summary.js";
|
|
|
13
13
|
import { generateReportFromThreadDump, analyzeThreadDumpMarkdown, } from "./reporting.js";
|
|
14
14
|
// Handle --help
|
|
15
15
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
16
|
-
console.log(`mcp-jvm-diagnostics v0.1.
|
|
16
|
+
console.log(`mcp-jvm-diagnostics v0.1.7 — MCP server for JVM diagnostics
|
|
17
17
|
|
|
18
18
|
Usage:
|
|
19
19
|
mcp-jvm-diagnostics [options]
|
|
@@ -33,7 +33,7 @@ Tools provided:
|
|
|
33
33
|
}
|
|
34
34
|
const server = new McpServer({
|
|
35
35
|
name: "mcp-jvm-diagnostics",
|
|
36
|
-
version: "0.1.
|
|
36
|
+
version: "0.1.7",
|
|
37
37
|
});
|
|
38
38
|
// --- Tool: analyze_thread_dump ---
|
|
39
39
|
server.tool("analyze_thread_dump", "Parse a JVM thread dump (jstack output) and analyze thread states, detect deadlocks, identify lock contention hotspots, and find thread starvation patterns. Handles both platform threads and virtual threads (Java 21+).", {
|
|
@@ -282,10 +282,10 @@ function formatBytes(bytes) {
|
|
|
282
282
|
return `${sign}${abs} B`;
|
|
283
283
|
}
|
|
284
284
|
// --- Tool: analyze_jfr ---
|
|
285
|
-
server.tool("analyze_jfr", "Parse JDK Flight Recorder summary output
|
|
285
|
+
server.tool("analyze_jfr", "Parse JDK Flight Recorder summary output and analyze event distribution, detect performance hotspots, GC pressure, lock contention, I/O patterns, and excessive allocations. Input must be the text printed to stdout by `jfr summary <recording.jfr>` — not the binary .jfr file itself.", {
|
|
286
286
|
jfr_summary: z
|
|
287
287
|
.string()
|
|
288
|
-
.describe("The
|
|
288
|
+
.describe("The stdout text from running `jfr summary <recording.jfr>` (a text table of event types, counts, and sizes — not the binary .jfr file)"),
|
|
289
289
|
}, async ({ jfr_summary }) => {
|
|
290
290
|
try {
|
|
291
291
|
const summary = parseJfrSummary(jfr_summary);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-jvm-diagnostics",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "MCP server for JVM diagnostics — analyze thread dumps, detect deadlocks, parse GC logs, and get JVM tuning recommendations",
|
|
5
5
|
"mcpName": "io.github.dmitriusan/mcp-jvm-diagnostics",
|
|
6
6
|
"author": "Dmytro Lisnichenko",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"url": "https://github.com/Dmitriusan/mcp-jvm-diagnostics/issues"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@mcp-java-suite/license": "
|
|
56
|
+
"@mcp-java-suite/license": "npm:mcp-java-suite-license@^0.1.0",
|
|
57
57
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
58
58
|
"zod": "^3.24.2"
|
|
59
59
|
},
|