{"id":48904588,"url":"https://github.com/SegfaultSorcerer/heap-seance","last_synced_at":"2026-04-19T10:01:15.110Z","repository":{"id":344499623,"uuid":"1181973281","full_name":"SegfaultSorcerer/heap-seance","owner":"SegfaultSorcerer","description":"MCP server that channels JVM forensics into structured leak verdicts — for Claude Code.","archived":false,"fork":false,"pushed_at":"2026-03-15T11:45:35.000Z","size":2789,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-15T11:51:49.211Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SegfaultSorcerer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-14T21:50:58.000Z","updated_at":"2026-03-15T11:45:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SegfaultSorcerer/heap-seance","commit_stats":null,"previous_names":["segfaultsorcerer/heap-seance"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/SegfaultSorcerer/heap-seance","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SegfaultSorcerer%2Fheap-seance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SegfaultSorcerer%2Fheap-seance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SegfaultSorcerer%2Fheap-seance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SegfaultSorcerer%2Fheap-seance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SegfaultSorcerer","download_url":"https://codeload.github.com/SegfaultSorcerer/heap-seance/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SegfaultSorcerer%2Fheap-seance/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32002361,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-16T19:00:43.474Z","updated_at":"2026-04-19T10:01:15.104Z","avatar_url":"https://github.com/SegfaultSorcerer.png","language":"Python","funding_links":[],"categories":["Projects"],"sub_categories":["Performance analysis"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/banner.png\" alt=\"Heap Seance\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eHeap Seance\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eSummoning retained objects from the heap — so you can interrogate what refuses to die.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"LICENSE-MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"MIT\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE-APACHE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-Apache_2.0-blue.svg\" alt=\"Apache 2.0\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.10+-green.svg\" alt=\"Python 3.10+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/JDK-17+-orange.svg\" alt=\"JDK 17+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/MCP-server-purple.svg\" alt=\"MCP Server\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Claude_Code-plugin-blueviolet.svg\" alt=\"Claude Code Plugin\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  An MCP server + CLI toolkit that channels the spirits of \u003ccode\u003ejcmd\u003c/code\u003e, \u003ccode\u003ejmap\u003c/code\u003e, \u003ccode\u003ejstat\u003c/code\u003e, \u003ccode\u003ejfr\u003c/code\u003e, Eclipse MAT, and async-profiler into a structured leak investigation workflow — designed to run inside \u003ca href=\"https://docs.anthropic.com/en/docs/claude-code\"\u003eClaude Code\u003c/a\u003e.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  2 slash commands. 8 MCP tools. Conservative by default.\n\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#how-it-works\"\u003eHow It Works\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#quick-start\"\u003eQuick Start\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#mcp-tools\"\u003eMCP Tools\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#investigation-workflow\"\u003eWorkflow\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#prerequisites\"\u003ePrerequisites\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## How It Works\n\nHeap Seance follows a two-stage escalation model. No deep forensics unless the evidence demands it.\n\n```\n /leak-scan                          /leak-deep\n     |                                   |\n     v                                   v\n  3x class histogram               (all of scan, plus)\n  + GC pressure snapshot            JFR recording\n     |                              heap dump\n     v                              MAT leak suspects\n  monotonic growth?                 async-profiler alloc profile\n  old-gen pressure?                     |\n     |                                  v\n     +--- both true? -----\u003e auto-escalate to deep\n     |\n     +--- otherwise ------\u003e verdict + next steps\n```\n\n**Confidence is earned, not assumed.** `high` requires at least two independent strong signals. A single growing class is `watch`. Growth plus GC pressure is `suspicious`. Add a MAT dominator or JFR correlation and you get `probable_memory_leak`.\n\n## Quick Start\n\nRequires [uv](https://docs.astral.sh/uv/getting-started/installation/), Python 3.10+, and a JDK 17+ for tooling (the target app can run any Java version).\n\n### 1. Clone\n\n```bash\ngit clone https://github.com/your-org/heap-seance.git\n```\n\n### 2. Add `.mcp.json` to your Java project\n\nIn the project you want to investigate, create a `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"heap-seance\": {\n      \"command\": \"uv\",\n      \"args\": [\"run\", \"--directory\", \"/path/to/heap-seance\", \"python\", \"-m\", \"heap_seance_mcp.server\"],\n      \"env\": {\n        \"JAVA_HOME\": \"/path/to/jdk-17\",\n        \"MAT_BIN\": \"/path/to/ParseHeapDump.sh\",\n        \"ASYNC_PROFILER_BIN\": \"/path/to/asprof\"\n      }\n    }\n  }\n}\n```\n\n`--directory` points to where you cloned Heap Seance. `uv run` handles the virtual environment and dependencies automatically. `ASYNC_PROFILER_BIN` is optional — if missing, deep mode continues with JFR + MAT.\n\n### 3. Copy the Claude Code commands\n\nCopy the `.claude/commands/` folder into your Java project so the `/leak-scan` and `/leak-deep` slash commands are available:\n\n```bash\ncp -r /path/to/heap-seance/.claude/commands/ .claude/commands/\n```\n\n### 4. Run\n\n```bash\n/leak-scan my-service        # conservative scan\n/leak-deep 12345             # full forensics by PID\n```\n\nHeap Seance resolves the target process, collects evidence, and returns a structured verdict.\n\n## MCP Tools\n\n| Tool | What it does |\n|------|-------------|\n| `java_list_processes()` | Discover running JVMs via `jcmd -l` |\n| `java_class_histogram(pid)` | Snapshot live object counts per class |\n| `java_gc_snapshot(pid)` | Sample `jstat -gcutil` over time |\n| `java_jfr_start(pid)` | Capture a JFR recording |\n| `java_jfr_summary(jfr_file)` | Summarize JFR event types and counts |\n| `java_heap_dump(pid)` | Full heap dump (`.hprof`) |\n| `java_mat_suspects(heap_dump)` | Run MAT leak suspects analysis |\n| `java_async_alloc_profile(pid)` | Allocation flame graph via async-profiler |\n\nEvery tool returns the same unified schema:\n\n```json\n{\n  \"status\": \"ok | warn | error\",\n  \"evidence\": [\"...\"],\n  \"metrics\": {},\n  \"confidence\": \"none | low | medium | high\",\n  \"next_recommended_action\": \"...\",\n  \"raw_artifact_path\": \"...\"\n}\n```\n\n## Investigation Workflow\n\n1. **Start your app** and let it initialize fully.\n2. **`/leak-scan \u003cname-or-pid\u003e`** — takes the first histogram snapshot.\n3. **Exercise the suspect behavior** — the scan prompts you between each of the 3 histogram samples to perform the action you suspect is leaking (open/close views, send requests, repeat workflows). This is critical — without load between samples, leaks stay invisible.\n4. **Read the verdict.** Focus on `Confidence`, `Key Evidence`, `Suspect Types`.\n5. **`/leak-deep \u003cname-or-pid\u003e`** if the scan flags growth, or if you want full forensics regardless.\n6. **Fix and re-scan.** Bounded caches, weak refs, listener cleanup — then `/leak-scan` again to confirm the signal drops.\n7. **Keep artifacts.** `.jfr`, `.hprof`, and MAT reports are saved for team review.\n\n### What you get back\n\n**`/leak-scan`** returns: Verdict, Confidence, Key Evidence, Suspect Types, Artifacts, Next Steps.\n\n**`/leak-deep`** goes further: Verdict, Confidence, Root Holder Hypothesis (who retains the growing objects and via which field/chain), Supporting Evidence, Artifacts, Remediation Hypotheses (concrete fix suggestions), Verification Plan.\n\n### Confidence ladder\n\n| Confidence | What it means | Signals required |\n|------------|--------------|-----------------|\n| `none` | No leak evidence | — |\n| `low` | Weak growth, no GC pressure | histogram only |\n| `medium` | Growth + GC is losing | histogram + GC pressure |\n| `high` | Probable leak, corroborated | histogram + GC + MAT/JFR |\n\n## Prerequisites\n\n**Tooling JDK** (required):\n- JDK 17+ for `jcmd`, `jmap`, `jstat` — set via `JAVA_HOME` in `.mcp.json`\n- The target application can run any Java version (including Java 8)\n\n**Deep forensics** (for `/leak-deep`):\n- [Eclipse MAT CLI](https://eclipse.dev/mat/downloads.php) (`ParseHeapDump.sh` / `.bat`) — required for deep mode\n- [async-profiler](https://github.com/async-profiler/async-profiler/releases) — optional tie-breaker\n\n**Optional tools:**\n- `jfr` CLI — used for JFR summary if available, falls back to `jcmd JFR.view` otherwise. JFR is skipped entirely for Java 8 targets (incompatible format).\n\nCheck your setup:\n\n```bash\n./scripts/check_prereqs.sh          # macOS / Linux\nscripts\\check_prereqs.bat           # Windows\n```\n\n### Environment overrides\n\nSet these in your `.mcp.json` `env` block (recommended) or as shell variables:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `JAVA_HOME` | recommended | JDK 17+ installation path — `$JAVA_HOME/bin` is searched first for `jcmd`, `jmap`, `jstat`, `jfr`. Also used to launch MAT with the correct Java version. |\n| `MAT_BIN` | for deep mode | Path to `ParseHeapDump.sh` (macOS/Linux) or `.bat` (Windows) |\n| `ASYNC_PROFILER_BIN` | optional | Path to async-profiler binary — tie-breaker evidence, deep mode works without it |\n| `HEAP_SEANCE_ARTIFACT_DIR` | optional | Where `.jfr`, `.hprof`, and reports are saved (default: system temp dir) |\n| `MCP_TRANSPORT` | optional | Transport protocol: `stdio` (default), `sse`, or `streamable-http` |\n| `MCP_HOST` | optional | Bind address for SSE/HTTP transport (default: `0.0.0.0`) |\n| `MCP_PORT` | optional | Port for SSE/HTTP transport (default: `8000`) |\n\nCLI flags `--sse` and `--streamable-http` can be used instead of `MCP_TRANSPORT`.\n\nSee `.mcp.json.example` for a full config template.\n\n### Compatibility notes\n\n- **Java 8 targets**: histogram + GC + MAT work fully. JFR is skipped (v0.9 format incompatible with modern tools).\n- **Windows**: MAT works via `ParseHeapDump.bat`. async-profiler is optional — if missing, deep mode continues with JFR + MAT. Locale-specific decimal separators (comma vs dot) in `jstat` output are handled automatically.\n- **MAT + JAVA_HOME**: MAT is launched with the JDK from `JAVA_HOME`, so it works even if the system default Java is too old for MAT.\n\n## CLI Usage (without Claude Code)\n\n```bash\nuv run heap-seance --mode scan --match your-app\nuv run heap-seance --mode deep --pid 12345 --output json\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eInstalling uv\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\n# macOS / Linux\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n\n# Windows (PowerShell)\npowershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/uv/install.ps1 | iex\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eManual setup (without uv)\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\npython3 -m venv .venv\nsource .venv/bin/activate       # Windows: .\\.venv\\Scripts\\Activate.ps1\npip install -e .\n\nheap-seance --mode scan --match your-app\n```\n\n\u003c/details\u003e\n\n## Tests\n\n```bash\npython3 -m unittest discover -s tests -p \"test_*.py\"\n```\n\nExample Java scenarios for validation live in `examples/java-scenarios/` — a real leak, a bounded cache (no leak), and a burst allocator (no leak).\n\n## Contributing\n\nContributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding tools, signals, and skills.\n\n## License\n\nThis project is dual-licensed under either of\n\n- [Apache License, Version 2.0](LICENSE-APACHE)\n- [MIT License](LICENSE-MIT)\n\nat your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSegfaultSorcerer%2Fheap-seance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSegfaultSorcerer%2Fheap-seance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSegfaultSorcerer%2Fheap-seance/lists"}