MCP server for jstall — exposes JVM diagnostics as tools for Claude and other MCP clients.
- Node.js 18+
- Java 17+ on the machine running the server (target JVM can be Java 11+)
The simplest way if you don't have jstall installed yet:
claude mcp add jstall -- npx -y @bechberger/jstall-mcp@latestIf you already have jstall installed, two hidden helper commands are also available:
jstall install-claude-mcp # writes the MCP entry to ~/.claude/settings.json
jstall install-claude-skill # symlinks the skill into ~/.claude/skills/jstall/Then restart Claude Code and you're ready to go.
code --add-mcp '{"name":"jstall","command":"npx","args":["-y","@bechberger/jstall-mcp@latest"]}'Then reload the VS Code window. The jstall tools will be available in Copilot Chat.
Add to ~/.claude/settings.json (Claude Code) or your Claude Desktop MCP config:
{
"mcpServers": {
"jstall": {
"command": "npx",
"args": ["-y", "@bechberger/jstall-mcp"]
}
}
}The JAR is bundled in the npm package — no separate jstall installation needed.
To use a local jstall build instead of downloading the JAR:
{
"mcpServers": {
"jstall": {
"command": "npx",
"args": ["-y", "@bechberger/jstall-mcp"],
"env": {
"JSTALL_JAR": "/path/to/jstall/target/jstall.jar"
}
}
}
}Once installed, talk to Claude naturally. Claude discovers JVMs, picks the right commands, and interprets the output.
Typical starting points:
"What is my Java application doing right now?"
"My Spring Boot app is slow — what's happening?"
"Is there a deadlock in PID 12345?"
"Generate a flamegraph for my app."
"Diagnose the JVM running MyService on prod-host."
What Claude does:
- Calls
jstall_run(["list"])to discover running JVMs (unless you gave a PID or name) - Calls
jstall_run(["status", "--intelligent-filter", "--no-native", "<pid>"])for an initial read - Interprets the output and follows up with targeted commands:
- High CPU →
most-work+flame - Deadlock →
deadlock+dependency-graph - Stuck threads → multi-dump
status+waiting-threads+dependency-tree - Memory growth →
gc-heap-info+ allocation flamegraph - Classloader leak →
vm-metaspace+vm-classloader-stats
- High CPU →
Remote JVMs:
"List JVMs on user@prod-host"
"Run a status check on the Cloud Foundry app my-cf-app"
"Is there a deadlock in the app running on staging-server?"
Claude uses jstall_remote automatically when you mention a hostname or CF app name.
Flamegraphs:
Claude will tell you the output path and ask you to open it in a browser. The profiling step blocks for the duration (default 10s), so expect a short wait.
"Generate a CPU flamegraph for PID 12345"
→ Claude runs flame, reports: "Flamegraph saved to /tmp/flame-12345.html — open in your browser."
"Profile memory allocations for 20 seconds"
→ Claude runs flame --event=alloc --duration=20s
Recordings:
"Capture a recording of PID 12345 for later analysis"
→ Claude runs record create, tells you the ZIP path
"Analyze this recording: /tmp/rec.zip"
→ Claude runs status + flame against the ZIP
Install the skill to give Claude a built-in triage decision tree and scenario runbooks:
ln -s "$(npm root -g)/@bechberger/jstall-mcp/skills/jstall" ~/.claude/skills/jstallOr if you have jstall installed, use the hidden helper command:
jstall install-claude-skillOr from a local clone:
ln -s /path/to/jstall/mcp/skills/jstall ~/.claude/skills/jstallThe skill activates automatically when you ask about JVM performance, deadlocks, profiling, or anything jstall-related.
| Tool | Description |
|---|---|
jstall_run |
Run any jstall command on a local JVM |
jstall_remote |
Run any jstall command on a remote JVM via SSH or Cloud Foundry |
jstall_help |
Show help for any jstall command |
{ "args": ["status", "--intelligent-filter", "--no-native", "12345"] }
{ "args": ["list"] }
{ "args": ["flame", "--output=/tmp/flame.html", "--duration=15s", "12345"] }
{ "args": ["record", "create", "--count=3", "--output=/tmp/rec.zip", "12345"] }{ "type": "ssh", "target": "user@prod-host", "args": ["list"] }
{ "type": "ssh", "target": "user@prod-host", "args": ["status", "--intelligent-filter", "--no-native", "12345"] }
{ "type": "cf", "target": "my-cf-app", "args": ["status", "--intelligent-filter", "12345"] }Remote support requires jstall available on the remote host (in PATH or via jbang). Linux/macOS only on the remote side.
{} // list all commands
{ "command": "status" } // flags for status
{ "command": "flame" } // flags for flame
{ "command": "record create" } // flags for record create subcommand| Variable | Description |
|---|---|
JSTALL_JAR |
Path to jstall.jar — overrides bundled JAR |
JSTALL_JAVA |
Path to java binary — overrides auto-detected Java 17+ |
The server resolves jstall.jar in this order:
--jar <path>CLI argumentJSTALL_JARenvironment variable- Bundled
lib/jstall.jarin the npm package ../../target/jstall.jarrelative to the package (local repo build)
git clone https://github.com/parttimenerd/jstall
cd jstall/mcp
npm install # downloads jstall.jar and compiles TypeScript
npm run build # compile TypeScript only
npm test # run test suite (77 tests; integration tests skip if JAR absent)To use a local jstall build instead of downloading:
cd jstall && mvn package -DskipTests
cd mcp && npm install # picks up ../target/jstall.jar automatically- Bump the version in
package.jsonandsrc/server.tsto match the jstall release. - Build and test:
npm run build npm test - Publish (requires npm OTP if 2FA is enabled):
npm publish --access public --otp=<your-OTP>
MIT