{
  "markdown": "# javaperf\n\n[![npm version](https://img.shields.io/npm/v/javaperf.svg)](https://www.npmjs.com/package/javaperf)\n\n> MCP (Model Context Protocol) server for profiling Java applications via JDK utilities (jcmd, jfr, jps)\n\nEnables AI assistants to diagnose performance, analyze threads, and inspect JFR recordings without manual CLI usage.\n\n📦 **Install**: `npm install -g javaperf` or use via npx\n🌐 **npm**: https://www.npmjs.com/package/javaperf\n\n## How to connect to Claude Desktop / IDE\n\nAdd the server to your MCP config. Example for **claude_desktop_config.json**:\n\n**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n**Linux:** `~/.config/Claude/claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"javaperf\"]\n    }\n  }\n}\n```\n\nFor **Cursor IDE**: Settings → Features → Model Context Protocol → Edit Config, then add the same block inside `mcpServers`. See the [Integration](#integration) section for more options (local dev, custom `JAVA_HOME`, etc.).\n\n## Requirements\n\n- **Node.js** v18+\n- **JDK** 8u262+ or 11+ with JFR support\n\nJDK tools (`jps`, `jcmd`, `jfr`) are auto-detected via `JAVA_HOME` or `which java`. If not found, set `JAVA_HOME` to your JDK root.\n\n## Quick Start\n\n### For Users (using npm package)\n\n```bash\n# No installation needed - use directly in Cursor/Claude Desktop\n# Just configure it as described in Integration section below\n```\n\n### For Developers\n\n1. Clone the repository:\n```bash\ngit clone https://github.com/theSharque/mcp-jperf.git\ncd mcp-jperf\n```\n\n2. Install dependencies:\n```bash\nnpm install\n```\n\n3. Build the project:\n```bash\nnpm run build\n```\n\n## Usage\n\n### Development Mode\n\n```bash\nnpm run dev\n```\n\n### Production Mode\n\n```bash\nnpm start\n```\n\n### MCP Inspector\n\nDebug and test with MCP Inspector:\n```bash\nnpx @modelcontextprotocol/inspector node dist/index.js\n```\n\n## Integration\n\n### Cursor IDE\n\n1. Open Cursor Settings → Features → Model Context Protocol\n2. Click \"Edit Config\" button\n3. Add one of the configurations below\n\n#### Option 1: Via npm (Recommended)\n\nInstalls from npm registry automatically:\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"javaperf\"]\n    }\n  }\n}\n```\n\n#### Option 2: Via npm link (Development)\n\nFor local development with live changes:\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"javaperf\"\n    }\n  }\n}\n```\n\nRequires: `cd /path/to/mcp-jperf && npm link -g`\n\n#### Option 3: Direct path\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"node\",\n      \"args\": [\"dist/index.js\"],\n      \"cwd\": \"${workspaceFolder}\",\n      \"env\": {\n        \"JAVA_HOME\": \"/path/to/your/jdk\"\n      }\n    }\n  }\n}\n```\n\nIf `list_java_processes` fails with \"jps not found\", the MCP server may not inherit your shell's `JAVA_HOME`. Add the `env` block above with your JDK root path (e.g. `/usr/lib/jvm/java-17` or `~/.sdkman/candidates/java/current`).\n\n### Claude Desktop\n\nEdit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\\Claude\\claude_desktop_config.json` (Windows):\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"javaperf\"]\n    }\n  }\n}\n```\n\n### Continue.dev\n\nEdit `.continue/config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"javaperf\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"javaperf\"]\n    }\n  }\n}\n```\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `list_java_processes` | List running Java processes (pid, mainClass, args). Use `topN` (default 10) to limit. |\n| `start_profiling` | Start JFR. Pass `pid`, `duration` (seconds). Optional: `preset` (default effective: `profile`), `settingsFile` (path to `.jfc`, mutually exclusive with `preset`), `memorysize`, `stackdepth` (default 128). |\n| `profile_jfr_network` | Socket I/O summary from `.jfr` (`jdk.SocketRead`, `jdk.SocketWrite`). Optional `filepath` (default new_profile), `topN`. |\n| `profile_jfr_file_io` | File read/write summary (`jdk.FileRead`, `jdk.FileWrite`). Optional `filepath`, `topN`. |\n| `profile_jfr_locks` | Monitor contention (`JavaMonitorBlocked`) and j.u.c parking (`ThreadPark`). Optional `filepath`, `topN`. Live waits: `analyze_threads structured=true`. |\n| `profile_jfr_native` | Native-method CPU hotspots (`jdk.NativeMethodSample`). Optional `filepath`, `topN`. |\n| `native_memory_summary` | `jcmd VM.native_memory summary` — requires JVM with `-XX:NativeMemoryTracking=summary` or `detail`. Pass `pid`. |\n| `gc_class_stats` | `jcmd GC.class_stats` when available (often JDK 21+). Pass `pid`. |\n| `gc_finalizer_info` | `jcmd GC.finalizer_info`. Pass `pid`. |\n| `compiler_codecache` | `jcmd Compiler.codecache`. Pass `pid`. |\n| `compiler_queue` | `jcmd Compiler.queue`. Pass `pid`. |\n| `list_jfr_recordings` | List active JFR recordings for a process. Use before `stop_profiling` to get `recordingId`. |\n| `stop_profiling` | Stop recording and save to recordings/new_profile.jfr. Requires `pid` and `recordingId`. |\n| `check_deadlock` | Check for Java-level deadlocks. Returns structured JSON with threads, locks, and cycle. |\n| `analyze_threads` | Thread dump (jstack) with deadlock summary. Pass `pid`, optional `topN` (default 10), `structured` (JSON lock-wait chains). Live snapshot; historical locks: `profile_jfr_locks`. |\n| `heap_histogram` | Class histogram (GC.class_histogram). Pass `pid`, optional `topN` (20), `all` (triggers full GC — may pause app). Static snapshot; use `heap_live_histogram_diff` for growth. |\n| `heap_live_histogram_diff` | Two histograms spaced by `intervalSeconds` (default 5). Top classes by instance/byte growth. First step in memory-leak workflow. Pass `pid`, optional `topN`, `all`, `minInstanceDelta`. |\n| `heap_dump` | Create .hprof for MAT/VisualVM. After `heap_live_histogram_diff`, use MAT Path to GC Roots. Pass `pid`. Saved to recordings/heap_dump.hprof. |\n| `heap_info` | Brief heap summary. Pass `pid`. |\n| `vm_info` | JVM info: uptime, version, flags. Pass `pid`. |\n| `trace_method` | Build call tree for a method from .jfr. Pass `className`, `methodName`. Optional: `filepath` (default new_profile), `topN`. |\n| `parse_jfr_summary` | Parse .jfr into summary: top methods, GC stats, anomalies. Optional: `filepath` (default new_profile), `events`, `topN`. |\n| `profile_memory` | Memory profile: top allocators by bytes/count, allocation stacks, OldObjectSample by class. Optional: `filepath`, `topN`, `sortBy` (`bytes`/`count`). Pair with `gc_efficiency`, `heap_live_histogram_diff`. |\n| `gc_efficiency` | GC efficiency from .jfr: pause vs freed bytes per collector. Optional: `filepath`, `topN`. After `stop_profiling`. |\n| `profile_time` | CPU bottleneck profile (bottom-up). Optional: `filepath` (default new_profile), `topN`. |\n| `profile_frequency` | Call frequency profile (leaf frames). Optional: `filepath` (default new_profile), `topN`. |\n\n## Example Workflow\n\n1. **List processes** → `list_java_processes`\n2. **Start recording** → `start_profiling` with `pid` and `duration` (e.g. 60)\n3. Wait for `duration` seconds (or let it run)\n4. **Check recordings** (optional) → `list_jfr_recordings` to get `recordingId`\n5. **Stop and save** → `stop_profiling` with `pid` and `recordingId`\n6. **Analyze** → `parse_jfr_summary`, `profile_memory`, `gc_efficiency`, `profile_time`, `profile_frequency`, `trace_method`, `profile_jfr_network`, `profile_jfr_file_io`, `profile_jfr_locks`, or `profile_jfr_native` (events must exist in the recording — use `start_profiling` with a suitable preset or `.jfc` via `settingsFile`)\n\n## Example Workflow: Memory leak hypothesis\n\n1. **List processes** → `list_java_processes`\n2. **Find growing classes** → `heap_live_histogram_diff` with `pid`, `intervalSeconds: 5`\n3. **Record under load** → `start_profiling` → wait → `stop_profiling`\n4. **Allocation profile** → `profile_memory` on `new_profile` (check `oldObjectSamplesByClass` for suspect class)\n5. **GC pressure** → `gc_efficiency` on the same `.jfr`\n6. **Confirm retention** → `heap_dump` → Eclipse MAT → Path to GC Roots (exclude weak/soft references)\n7. AI builds a coherent leak hypothesis from the combined results (no dedicated tool)\n\n## Remote JVM (stdio MCP)\n\njavaperf uses stdio MCP and attaches to JVMs via local `jps`/`jcmd`. That only works **on the OS account and host where the MCP process runs**.\n\nTo diagnose a JVM on another machine:\n\n- Run the MCP server (your IDE connector, Cursor, or Claude Desktop) **on that machine**, for example SSH remote workspace, Codespaces, CI runner checkout on the server, or a shell session on the same host as the process.\n- **Do not** rely on piping `jcmd` over plain SSH from another host unless you deliberately run MCP there; attaching across hosts is outside this server’s scope.\n\nRequirements (same user, local attach) listed under **Limitations** still apply.\n\n## Limitations\n\n- **Sampling**: JFR samples ~10ms; fast methods may not appear in ExecutionSample\n- **Local only**: Runs on the machine where MCP is started\n- **Permissions**: Must run as same user as target JVM for jcmd access\n",
  "bytes": 9152,
  "sha": "3edb22f8d99c832c5dd643c11ca404f194e34632b733be74e53dce165bfb4c6d",
  "repo_slug": "thesharque/mcp-jperf",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_thesharque_javaperf_9b787058/readme"
}