Repository navigation
Add an MCP server for AI assistants to query heap dumps (3/4) - #123
Open
miguelnieto wants to merge 3 commits into
Open
miguelnieto wants to merge 3 commits into
miguelnieto wants to merge 3 commits into
Conversation
miguelnieto
force-pushed
the
03_mcp-server
branch
2 times, most recently
from
October 17, 2026 01:21
afc0ddc to
bbbdd11
Compare
miguelnieto
force-pushed
the
03_mcp-server
branch
from
November 7, 2026 17:12
bbbdd11 to
8090480
Compare
BREAKING: requires MAT 1.17.0+ and Java 21. org.eclipse.mat.api 1.17.0 declares Bundle-RequiredExecutionEnvironment: JavaSE-21, so the execution environment cannot go lower. Users on older MAT must stay on 1.6.x. Platform - Target platform moved from Eclipse 2022-12 to Eclipse 4.40, matching the Eclipse release MAT 1.17.0 builds against. - MAT bundles come from the MAT 1.17.0 update site rather than an Eclipse simultaneous release, so the MAT API version matches the MAT users run. Only the units this plugin needs are listed; the full org.eclipse.mat.feature.feature.group would drag in mat.chart and therefore BIRT and Rhino, which are unused. - Java 21: BREE, executionEnvironment, compiler source/target, CI matrix, README requirements. Calcite 1.36 -> 1.42.0 - Aligned Calcite/Guava versions between MatCalcitePlugin/pom.xml and MatCalciteTargetPlatform.target (Guava 33.7.2-jre in both, after Renovate updated the pom only). They had drifted apart (1.41.0 vs 1.36.0) because Renovate only updates poms, not Tycho target definitions. - Avatica 1.29.0 instead of the 1.28.0 Calcite 1.42.0 asks for: Avatica before 1.29.0 has CVE-2026-70410 (unsafe reflection in plugin instantiation, CVSS 8.8). Declared before calcite-core so Maven compiles against the Jackson 2.22.2 it brings, which the target ships. - Added httpclient5/httpcore5 (new Avatica 1.28 dependencies) and org.jooq:joou-java-6 to the target platform and to Import-Package. Without them: NoClassDefFoundError for org/apache/hc/core5/util/Timeout and org/joou/UInteger. - Excluded jakarta.transaction:jakarta.transaction-api from commons-dbcp2: it has an unsatisfiable Import-Package (javax.enterprise.context) and blocked geronimo-jta_1.1_spec from supplying javax.transaction. ORDER BY and joins on heap objects - Calcite 1.37+ sorts Map-typed values with Functions.compareMaps(), which calls entrySet(); HeapReference is a Map only for this['field'] and threw from entrySet(), so every ORDER BY over a heap object failed. entrySet() now returns one entry that orders like compareTo. - Calcite sorts merge-join inputs through entrySet() but merges them with compareTo, so both must give the same order, or matches are dropped (the class/class loader join counted 469 instead of 985). Both now order by address, which is also constant time: ordering by label rebuilt the label on every comparison (ORDER BY this on 4M objects: about 2 min vs 10 s). ORDER BY toString(this) gives label order. SQL functions - getHexAddress(x): the object address as 0x..., as MAT shows it. - getDominator(x) returned an error for objects dominated by the virtual root; it now returns null. Tests - testStackTraces tolerates MAT's own stack frame formatting, which changed in MAT commit 0c72944e ("Bug 581644"): "(Native Method)" became "(Object.java(Native Method))". - New: ORDER BY this in both directions, a merge join over a strict subset, the class/class loader join phrased three ways (985 each). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r, date functions Editor - Right-click menu (Run, Explain, Undo/Redo, Cut/Copy/Paste, Delete, Select All, Toggle Comment); keys are workbench commands in their own context, so F5, Ctrl+Enter and Ctrl+Space no longer go to MAT's OQL commands. - Schema browser beside the editor: classes by package, instanceof, thread stacks and functions, with columns and sizes; double-click inserts the name, quoted where SQL needs it. The filter is debounced and uses cached sorted names. - "SQL Reference" tab; theme colors (with dark theme defaults); completion pops up after '.' and '"'; object icons in results; navigation history restores and reruns a query. - Error underline at the right place for a selection and for Explain, and cleared on the next run. Cancel in the progress view and closing the tab stop a running query (QueryCancellation, checked by the heap scan). - Fixes: keys lost after a table result on GTK/Wayland (no active shell), editor scroll jump on a transient resize, Undo/Redo keys, leaked title image and colors, closed-tab cleanup, debug output on stdout. Open in SQL Editor - On MAT's object menus: a query for the selected objects (by address, one statement per class) or for a class row (all instances, or the row's objects for a partial histogram), added to the SQL tab of the objects' own dump. SQL - Date and time functions: toDateTime, toEpochMillis, millisToDateTime, secondsToDateTime, toDuration. - instanceof."java.lang.ref.Reference" (full class name as one identifier); identifiers quoted by Calcite's reserved words, not only SQL-92's. - CALCITE-1.42-QUERIES.md: what Calcite 1.37-1.42 adds to heap queries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MemoryAnalyzer -nosplash -application MatCalcitePlugin.mcp serves the Model Context Protocol on stdio (JSON-RPC with json-smart, already bundled; no new dependencies). Dumps stay open between calls. Tools - Dumps and schema: open/list/close, list_tables, describe_table. - SQL: sql_query (markdown, row limit), explain_sql, sql_reference, export_query (CSV, no row limit). - Per object, as on MAT's context menu: object_info, list_references, retained_set, path_to_gc_roots, immediate_dominators; mat_query for other MAT commands. - Analyses: heap_overview, histogram, leak_suspects (as data: class loader, accumulation point, path from a GC root, thread stack locals), compare_dumps, collection_contents, duplicate_strings, wasteful_collections. Cancellation - notifications/cancelled, cancel_query and timeout_seconds. A flag per call (QueryCancellation), never Thread.interrupt: MAT reads its indexes through a FileChannel, which an interrupt closes for good. A cancelled open deletes the index files it created. Security - The assistant reads heap contents, which can hold text written to steer it. mat_query refuses commands that read or write files, open other dumps or run reports; export_query writes .csv only inside the export directory (MAT_MCP_EXPORT_DIR or the dump's), atomically, with formula cells defused. Slow regular expressions in histogram filters stop on timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
miguelnieto
force-pushed
the
03_mcp-server
branch
from
November 7, 2026 21:51
8090480 to
5f72e7d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a headless Model Context Protocol server, so that AI assistants (Claude Code and other MCP clients) can investigate heap dumps. They query with SQL, use MAT's per-object actions, and run analyses that return data rather than prose.
How it works
MatCalcitePlugin.mcp, inplugin.xml.pingare handled at once on the reading thread, so they work while a long query runs.com.github.vlsi.mat.calcite.mcp. That package is exported only to the test bundle (x-friends).McpServerhandles JSON-RPC without stdio, so the tests drive it directly.Tools
open_heap_dump,list_heap_dumps,close_heap_dump,list_tables,describe_tablesql_query(markdown, row limit),explain_sql,sql_reference,export_query(CSV, all rows)object_info,list_references(incoming / outgoing),retained_set,path_to_gc_roots,immediate_dominatorsmat_query, e.g.find_leaks,top_consumers,dominator_treeheap_overview,histogram,leak_suspects,compare_dumps,collection_contents,duplicate_strings,wasteful_collectionscancel_queryResults show objects as
class @ 0xaddress, and the object tools take those addresses, so an assistant can chain calls. For example, it can find the biggest maps withsql_query, then askpath_to_gc_rootswhy one is alive.Some of the tools in more detail:
leak_suspectsreturns MAT's leak suspects as data rather than report text:duplicate_stringscounts string values by a 64-bit hash, not by keeping each text in memory.wasteful_collectionscounts 4 bytes per unused slot when the dump uses compressed pointers.Cancellation
notifications/cancelled, thecancel_querytool, andtimeout_seconds(default 300 s; opening a dump has no default limit).Thread.interrupt(). MAT reads its index files through aFileChannel, which an interrupt closes for good, and that breaks the dump until it is reopened. Instead, each call sets a flag (QueryCancellation, from SQL editor: schema browser, Open in SQL Editor, cancel, date functions (2/4) #122) that the heap scan, the analysis loops and MAT's progress listener check.open_heap_dumpdeletes the index files it created, matching only MAT's index file names.Security
The assistant reads heap contents. A heap can hold text written by outsiders, such as request bodies, messages or log lines, possibly written to steer an assistant. The server's instructions tell the assistant to treat heap text as data, never as instructions. Beyond that, the server limits what it can do:
export_querywrites only.csvfiles inside the export directory:MAT_MCP_EXPORT_DIR, or the dump's directory. It refuses other paths (../and symlinks included), writes through a temporary file moved atomically, and adds a leading'to cells and headers that a spreadsheet would run as formulas.mat_queryrefuses MAT commands that read or write files, open other dumps or run reports, judged by each argument's type and itsArgument.Advice. Examples:export_hprof,delta_histogram -baseline,create_report.compare_dumpscompares dumps that are already open.open_heap_dumpaccepts only regular files.^(.+)+\1!) stop at the timeout.Testing
./mvnw verifywith JDK 21: 101 tests pass, 1 skipped (@Ignoreonmaintoo).McpServerTestscovers:Over stdio with Claude Code: investigations on the test dump and on a 1.5 GB dump with 24M objects. Timings on the large dump:
duplicate_strings(4M strings)wasteful_collectionsheap_overview,leak_suspectsTwo servers can run on one MAT install at the same time.
Notes for reviewers
app.hprof, MAT deletes old index files matchingapp+([A-Za-z0-9]{1,20}\.)?index. That pattern also matchesapp.2.index, the index of a sibling dumpapp.2.hprof. The cleanup in this PR uses only MAT's exact index names, so it doesn't make this worse.duplicate_stringsneeds about 80 bytes per distinct value, which matters only for dumps with tens of millions of distinct strings;SIMILAR TOon a huge string) can't be interrupted;🤖 Generated with Claude Code