@memlab/mcp-server 2.1.1 → 2.18.1

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.
Files changed (175) hide show
  1. package/README.md +83 -3
  2. package/dist/analysis-budget.d.ts +71 -0
  3. package/dist/analysis-budget.d.ts.map +1 -0
  4. package/dist/analysis-budget.js +118 -0
  5. package/dist/analysis-budget.js.map +1 -0
  6. package/dist/guardrail.d.ts +24 -0
  7. package/dist/guardrail.d.ts.map +1 -0
  8. package/dist/guardrail.js +65 -0
  9. package/dist/guardrail.js.map +1 -0
  10. package/dist/heap-state.d.ts +53 -1
  11. package/dist/heap-state.d.ts.map +1 -1
  12. package/dist/heap-state.js +153 -10
  13. package/dist/heap-state.js.map +1 -1
  14. package/dist/index.js +38 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/tools/array-group-by.d.ts +12 -0
  17. package/dist/tools/array-group-by.d.ts.map +1 -0
  18. package/dist/tools/array-group-by.js +191 -0
  19. package/dist/tools/array-group-by.js.map +1 -0
  20. package/dist/tools/auto-investigate.d.ts.map +1 -1
  21. package/dist/tools/auto-investigate.js +1056 -52
  22. package/dist/tools/auto-investigate.js.map +1 -1
  23. package/dist/tools/cache-analysis.d.ts.map +1 -1
  24. package/dist/tools/cache-analysis.js +438 -21
  25. package/dist/tools/cache-analysis.js.map +1 -1
  26. package/dist/tools/check-health.d.ts.map +1 -1
  27. package/dist/tools/check-health.js +261 -1
  28. package/dist/tools/check-health.js.map +1 -1
  29. package/dist/tools/class-histogram.d.ts.map +1 -1
  30. package/dist/tools/class-histogram.js +142 -33
  31. package/dist/tools/class-histogram.js.map +1 -1
  32. package/dist/tools/closure-inspection.d.ts.map +1 -1
  33. package/dist/tools/closure-inspection.js +238 -25
  34. package/dist/tools/closure-inspection.js.map +1 -1
  35. package/dist/tools/detached-dom.d.ts.map +1 -1
  36. package/dist/tools/detached-dom.js +25 -3
  37. package/dist/tools/detached-dom.js.map +1 -1
  38. package/dist/tools/dev-artifacts.d.ts +33 -0
  39. package/dist/tools/dev-artifacts.d.ts.map +1 -0
  40. package/dist/tools/dev-artifacts.js +165 -0
  41. package/dist/tools/dev-artifacts.js.map +1 -0
  42. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  43. package/dist/tools/diff-snapshots.js +200 -48
  44. package/dist/tools/diff-snapshots.js.map +1 -1
  45. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  46. package/dist/tools/duplicated-strings.js +74 -12
  47. package/dist/tools/duplicated-strings.js.map +1 -1
  48. package/dist/tools/eval.d.ts.map +1 -1
  49. package/dist/tools/eval.js +189 -10
  50. package/dist/tools/eval.js.map +1 -1
  51. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  52. package/dist/tools/event-listener-leaks.js +235 -13
  53. package/dist/tools/event-listener-leaks.js.map +1 -1
  54. package/dist/tools/event-registry.d.ts +12 -0
  55. package/dist/tools/event-registry.d.ts.map +1 -0
  56. package/dist/tools/event-registry.js +183 -0
  57. package/dist/tools/event-registry.js.map +1 -0
  58. package/dist/tools/find-by-property.d.ts.map +1 -1
  59. package/dist/tools/find-by-property.js +113 -31
  60. package/dist/tools/find-by-property.js.map +1 -1
  61. package/dist/tools/find-by-shape.d.ts +12 -0
  62. package/dist/tools/find-by-shape.d.ts.map +1 -0
  63. package/dist/tools/find-by-shape.js +178 -0
  64. package/dist/tools/find-by-shape.js.map +1 -0
  65. package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
  66. package/dist/tools/find-nodes-by-class.js +50 -6
  67. package/dist/tools/find-nodes-by-class.js.map +1 -1
  68. package/dist/tools/for-each.d.ts.map +1 -1
  69. package/dist/tools/for-each.js +1 -1
  70. package/dist/tools/for-each.js.map +1 -1
  71. package/dist/tools/get-node.d.ts.map +1 -1
  72. package/dist/tools/get-node.js +6 -0
  73. package/dist/tools/get-node.js.map +1 -1
  74. package/dist/tools/get-references.d.ts.map +1 -1
  75. package/dist/tools/get-references.js +35 -6
  76. package/dist/tools/get-references.js.map +1 -1
  77. package/dist/tools/get-referrers.d.ts.map +1 -1
  78. package/dist/tools/get-referrers.js +35 -6
  79. package/dist/tools/get-referrers.js.map +1 -1
  80. package/dist/tools/get-string.d.ts +12 -0
  81. package/dist/tools/get-string.d.ts.map +1 -0
  82. package/dist/tools/get-string.js +223 -0
  83. package/dist/tools/get-string.js.map +1 -0
  84. package/dist/tools/get-value.d.ts +12 -0
  85. package/dist/tools/get-value.d.ts.map +1 -0
  86. package/dist/tools/get-value.js +152 -0
  87. package/dist/tools/get-value.js.map +1 -0
  88. package/dist/tools/global-variables.d.ts.map +1 -1
  89. package/dist/tools/global-variables.js +54 -34
  90. package/dist/tools/global-variables.js.map +1 -1
  91. package/dist/tools/growth-signals.d.ts +12 -0
  92. package/dist/tools/growth-signals.d.ts.map +1 -0
  93. package/dist/tools/growth-signals.js +211 -0
  94. package/dist/tools/growth-signals.js.map +1 -0
  95. package/dist/tools/intern-opportunities.d.ts +12 -0
  96. package/dist/tools/intern-opportunities.d.ts.map +1 -0
  97. package/dist/tools/intern-opportunities.js +870 -0
  98. package/dist/tools/intern-opportunities.js.map +1 -0
  99. package/dist/tools/largest-objects.d.ts.map +1 -1
  100. package/dist/tools/largest-objects.js +37 -14
  101. package/dist/tools/largest-objects.js.map +1 -1
  102. package/dist/tools/load-snapshot.d.ts +70 -0
  103. package/dist/tools/load-snapshot.d.ts.map +1 -1
  104. package/dist/tools/load-snapshot.js +446 -17
  105. package/dist/tools/load-snapshot.js.map +1 -1
  106. package/dist/tools/object-cost-breakdown.d.ts +12 -0
  107. package/dist/tools/object-cost-breakdown.d.ts.map +1 -0
  108. package/dist/tools/object-cost-breakdown.js +439 -0
  109. package/dist/tools/object-cost-breakdown.js.map +1 -0
  110. package/dist/tools/object-shape.d.ts.map +1 -1
  111. package/dist/tools/object-shape.js +109 -2
  112. package/dist/tools/object-shape.js.map +1 -1
  113. package/dist/tools/pinch-points.d.ts.map +1 -1
  114. package/dist/tools/pinch-points.js +9 -9
  115. package/dist/tools/pinch-points.js.map +1 -1
  116. package/dist/tools/property-distribution.d.ts +12 -0
  117. package/dist/tools/property-distribution.d.ts.map +1 -0
  118. package/dist/tools/property-distribution.js +168 -0
  119. package/dist/tools/property-distribution.js.map +1 -0
  120. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  121. package/dist/tools/quick-diagnosis.js +65 -20
  122. package/dist/tools/quick-diagnosis.js.map +1 -1
  123. package/dist/tools/retainer-summary.d.ts.map +1 -1
  124. package/dist/tools/retainer-summary.js +90 -5
  125. package/dist/tools/retainer-summary.js.map +1 -1
  126. package/dist/tools/retainer-trace.d.ts.map +1 -1
  127. package/dist/tools/retainer-trace.js +173 -43
  128. package/dist/tools/retainer-trace.js.map +1 -1
  129. package/dist/tools/search-nodes.d.ts.map +1 -1
  130. package/dist/tools/search-nodes.js +10 -3
  131. package/dist/tools/search-nodes.js.map +1 -1
  132. package/dist/tools/search-strings.d.ts +12 -0
  133. package/dist/tools/search-strings.d.ts.map +1 -0
  134. package/dist/tools/search-strings.js +182 -0
  135. package/dist/tools/search-strings.js.map +1 -0
  136. package/dist/tools/sequence-analysis.d.ts +12 -0
  137. package/dist/tools/sequence-analysis.d.ts.map +1 -0
  138. package/dist/tools/sequence-analysis.js +244 -0
  139. package/dist/tools/sequence-analysis.js.map +1 -0
  140. package/dist/tools/server-status.d.ts +12 -0
  141. package/dist/tools/server-status.d.ts.map +1 -0
  142. package/dist/tools/server-status.js +41 -0
  143. package/dist/tools/server-status.js.map +1 -0
  144. package/dist/tools/shape-histogram.d.ts.map +1 -1
  145. package/dist/tools/shape-histogram.js +61 -16
  146. package/dist/tools/shape-histogram.js.map +1 -1
  147. package/dist/tools/sliced-strings.d.ts.map +1 -1
  148. package/dist/tools/sliced-strings.js +38 -15
  149. package/dist/tools/sliced-strings.js.map +1 -1
  150. package/dist/tools/snapshot-header.d.ts +28 -0
  151. package/dist/tools/snapshot-header.d.ts.map +1 -0
  152. package/dist/tools/snapshot-header.js +111 -0
  153. package/dist/tools/snapshot-header.js.map +1 -0
  154. package/dist/tools/snapshot-summary.d.ts.map +1 -1
  155. package/dist/tools/snapshot-summary.js +55 -13
  156. package/dist/tools/snapshot-summary.js.map +1 -1
  157. package/dist/tools/snapshots.d.ts +12 -0
  158. package/dist/tools/snapshots.d.ts.map +1 -0
  159. package/dist/tools/snapshots.js +93 -0
  160. package/dist/tools/snapshots.js.map +1 -0
  161. package/dist/tools/stale-collections.d.ts.map +1 -1
  162. package/dist/tools/stale-collections.js +248 -7
  163. package/dist/tools/stale-collections.js.map +1 -1
  164. package/dist/tools/trace-dominators.d.ts.map +1 -1
  165. package/dist/tools/trace-dominators.js +28 -1
  166. package/dist/tools/trace-dominators.js.map +1 -1
  167. package/dist/tools/weakmap-entries.d.ts +12 -0
  168. package/dist/tools/weakmap-entries.d.ts.map +1 -0
  169. package/dist/tools/weakmap-entries.js +156 -0
  170. package/dist/tools/weakmap-entries.js.map +1 -0
  171. package/dist/utils.d.ts +139 -2
  172. package/dist/utils.d.ts.map +1 -1
  173. package/dist/utils.js +448 -35
  174. package/dist/utils.js.map +1 -1
  175. package/package.json +3 -3
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import { z } from 'zod';
11
+ import { getSnapshot } from '../heap-state.js';
12
+ import { formatBytes, formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
13
+ export function registerSearchStrings(server) {
14
+ server.tool('memlab_search_strings', 'Search the content (stringValue) of all string nodes in the heap snapshot. ' +
15
+ 'Unlike memlab_search_nodes which searches by node name/class, this searches the ' +
16
+ 'actual text content of strings. Essential for finding string constants (error messages, ' +
17
+ 'event names, config keys, URLs) and tracing them back to their origin. ' +
18
+ 'Supports exact substring match and regex patterns. ' +
19
+ "⚠ Full-heap scan over every string's content — slow on very large heaps (millions of nodes); use a specific pattern and a small limit.", {
20
+ pattern: z
21
+ .string()
22
+ .describe('The search pattern. Plain text for substring match, or prefix with "/" for regex ' +
23
+ '(e.g., "/change:ack.*directPath/i" for case-insensitive regex).'),
24
+ limit: z
25
+ .number()
26
+ .optional()
27
+ .default(20)
28
+ .describe('Maximum number of matching strings to return (default 20)'),
29
+ min_length: z
30
+ .number()
31
+ .optional()
32
+ .default(0)
33
+ .describe('Minimum string length to search (default 0). Use to skip short strings.'),
34
+ max_length: z
35
+ .number()
36
+ .optional()
37
+ .describe('Maximum string length to search. Use to skip very large strings for faster results.'),
38
+ show_referrers: z
39
+ .boolean()
40
+ .optional()
41
+ .default(true)
42
+ .describe('Show which objects reference each matching string (default true). Disable for faster results when you only need the string values.'),
43
+ }, async ({ pattern, limit, min_length, max_length, show_referrers }) => {
44
+ try {
45
+ const snapshot = getSnapshot();
46
+ let regex = null;
47
+ let substring = null;
48
+ if (pattern.startsWith('/') && pattern.lastIndexOf('/') > 0) {
49
+ const lastSlash = pattern.lastIndexOf('/');
50
+ const regexPattern = pattern.slice(1, lastSlash);
51
+ const flags = pattern.slice(lastSlash + 1);
52
+ regex = new RegExp(regexPattern, flags);
53
+ }
54
+ else {
55
+ substring = pattern;
56
+ }
57
+ const matches = [];
58
+ let scannedCount = 0;
59
+ let totalStringNodes = 0;
60
+ snapshot.nodes.forEach(node => {
61
+ if (node.id <= 3)
62
+ return;
63
+ if (!node.isString)
64
+ return;
65
+ totalStringNodes++;
66
+ const strNode = node.toStringNode();
67
+ if (!strNode)
68
+ return;
69
+ const val = strNode.stringValue;
70
+ if (val.length < min_length)
71
+ return;
72
+ if (max_length != null && val.length > max_length)
73
+ return;
74
+ scannedCount++;
75
+ let isMatch = false;
76
+ if (regex) {
77
+ isMatch = regex.test(val);
78
+ }
79
+ else if (substring) {
80
+ isMatch = val.includes(substring);
81
+ }
82
+ if (!isMatch)
83
+ return;
84
+ const size = node.retainedSize;
85
+ let inserted = false;
86
+ for (let i = 0; i < matches.length; i++) {
87
+ if (size > matches[i].retainedSize) {
88
+ matches.splice(i, 0, {
89
+ nodeId: node.id,
90
+ stringValue: val,
91
+ selfSize: node.self_size,
92
+ retainedSize: size,
93
+ nodeType: node.type,
94
+ nodeName: node.name,
95
+ });
96
+ inserted = true;
97
+ break;
98
+ }
99
+ }
100
+ if (!inserted)
101
+ matches.push({
102
+ nodeId: node.id,
103
+ stringValue: val,
104
+ selfSize: node.self_size,
105
+ retainedSize: size,
106
+ nodeType: node.type,
107
+ nodeName: node.name,
108
+ });
109
+ if (matches.length > limit)
110
+ matches.length = limit;
111
+ });
112
+ const patternDesc = regex ? `regex ${pattern}` : `"${pattern}"`;
113
+ if (matches.length === 0) {
114
+ return toolResult(`No strings matching ${patternDesc} found.\n\n` +
115
+ `Scanned ${formatNumber(scannedCount)} of ${formatNumber(totalStringNodes)} string nodes` +
116
+ (min_length > 0 ? ` (filtered to length >= ${min_length})` : '') +
117
+ '.\n\n' +
118
+ '**Try:**\n' +
119
+ '- Use a shorter or less specific pattern\n' +
120
+ '- Use regex for flexible matching: `/partial.*match/i`\n' +
121
+ '- Remove min_length/max_length filters\n' +
122
+ '- Use `memlab_duplicated_strings` if looking for repeated strings');
123
+ }
124
+ const lines = [
125
+ `## String Content Search`,
126
+ `Found ${formatNumber(matches.length)} string(s) matching ${patternDesc} (scanned ${formatNumber(scannedCount)} of ${formatNumber(totalStringNodes)} string nodes)`,
127
+ '',
128
+ ];
129
+ const headers = ['ID', 'Preview', 'Length', 'Self Size', 'Retained'];
130
+ const rightCols = new Set([2, 3, 4]);
131
+ const rows = matches.map(m => {
132
+ const preview = m.stringValue.length > 80
133
+ ? m.stringValue.slice(0, 77) + '...'
134
+ : m.stringValue;
135
+ return [
136
+ `@${m.nodeId}`,
137
+ `"${preview.replace(/\n/g, '\\n').replace(/\|/g, '\\|')}"`,
138
+ formatNumber(m.stringValue.length),
139
+ formatBytes(m.selfSize),
140
+ formatBytes(m.retainedSize),
141
+ ];
142
+ });
143
+ lines.push(markdownTable(headers, rows, rightCols));
144
+ if (show_referrers && matches.length > 0) {
145
+ lines.push('');
146
+ lines.push('**Referrer context for top matches:**');
147
+ for (const m of matches.slice(0, 5)) {
148
+ const node = snapshot.getNodeById(m.nodeId);
149
+ if (!node)
150
+ continue;
151
+ const referrers = [];
152
+ let count = 0;
153
+ for (const edge of node.referrers) {
154
+ if (count >= 3)
155
+ break;
156
+ if (edge.fromNode.id <= 3)
157
+ continue;
158
+ referrers.push(`\`${String(edge.name_or_index)}\` on @${edge.fromNode.id} \`${edge.fromNode.name}\``);
159
+ count++;
160
+ }
161
+ if (referrers.length > 0) {
162
+ const preview = m.stringValue.length > 40
163
+ ? m.stringValue.slice(0, 37) + '...'
164
+ : m.stringValue;
165
+ lines.push(`- @${m.nodeId} "${preview.replace(/\n/g, '\\n')}": ${referrers.join(', ')}`);
166
+ }
167
+ }
168
+ }
169
+ lines.push('');
170
+ lines.push('**Suggested next steps:**');
171
+ const top = matches[0];
172
+ lines.push(`- Inspect string: \`memlab_get_string(${top.nodeId})\` for full value`);
173
+ lines.push(`- Trace retention: \`memlab_retainer_trace(${top.nodeId})\``);
174
+ lines.push(`- Find duplicates: \`memlab_retainer_summary\` with \`node_ids\` from matching strings`);
175
+ return toolResult(lines.join('\n'));
176
+ }
177
+ catch (err) {
178
+ return errorResult(err);
179
+ }
180
+ });
181
+ }
182
+ //# sourceMappingURL=search-strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-strings.js","sourceRoot":"","sources":["../../src/tools/search-strings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ export declare function registerSequenceAnalysis(server: McpServer): void;
12
+ //# sourceMappingURL=sequence-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/sequence-analysis.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAsEvE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2OhE"}
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import fs from 'fs';
11
+ import { z } from 'zod';
12
+ import memlabHeapAnalysis from '@memlab/heap-analysis';
13
+ const { getFullHeapFromFile } = memlabHeapAnalysis;
14
+ import { resolveSnapshotPath } from './load-snapshot.js';
15
+ import { formatBytes, formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
16
+ // A class key is "<type>::<name>". Value-named string "classes" (literal
17
+ // values used as the name, e.g. "554", "1780525701808.81", "o:10,add") are
18
+ // noise across a sequence — drop them like diff_snapshots does (§10).
19
+ function isNoiseClass(type, name) {
20
+ if (type !== 'string' && type !== 'concatenated string')
21
+ return false;
22
+ if (name.length < 8)
23
+ return true;
24
+ if (/^[\s\d.,:+-]*$/.test(name))
25
+ return true;
26
+ return false;
27
+ }
28
+ function buildHistogram(snapshot) {
29
+ const hist = new Map();
30
+ let nodeCount = 0;
31
+ let totalSize = 0;
32
+ snapshot.nodes.forEach(node => {
33
+ nodeCount++;
34
+ totalSize += node.self_size;
35
+ if (node.id <= 3)
36
+ return;
37
+ const key = `${node.type}::${node.name}`;
38
+ const e = hist.get(key);
39
+ if (e) {
40
+ e.count++;
41
+ e.selfSize += node.self_size;
42
+ }
43
+ else {
44
+ hist.set(key, { count: 1, selfSize: node.self_size });
45
+ }
46
+ });
47
+ return { hist, nodeCount, totalSize };
48
+ }
49
+ function classifyTrend(counts) {
50
+ let up = true;
51
+ let down = true;
52
+ for (let i = 1; i < counts.length; i++) {
53
+ if (counts[i] <= counts[i - 1])
54
+ up = false;
55
+ if (counts[i] >= counts[i - 1])
56
+ down = false;
57
+ }
58
+ const net = counts[counts.length - 1] - counts[0];
59
+ if (up && net > 0)
60
+ return 'monotonic-up';
61
+ if (down && net < 0)
62
+ return 'monotonic-down';
63
+ if (net > 0)
64
+ return 'grew-net';
65
+ return 'flat-or-mixed';
66
+ }
67
+ export function registerSequenceAnalysis(server) {
68
+ server.tool('memlab_sequence_analysis', 'Trend analysis across an ORDERED sequence of >=2 heap snapshots (the canonical "is anything growing unboundedly?" tool). Loads each snapshot transiently (does NOT change your active snapshot), builds per-class histograms, and reports each class\'s value at every step plus a growth verdict: "monotonic-up" (grew every step — strongest leak signal) vs "grew-net" (grew overall but not every step — often GC/navigation noise) vs flat/shrank. Also lists classes new since the baseline. Paths may be local, manifold:// URLs, or bare filenames.', {
69
+ paths: z
70
+ .array(z.string())
71
+ .min(2)
72
+ .describe('Ordered list of >=2 snapshot paths (oldest first). Each may be a local absolute path, a manifold:// URL, or a bare snapshot filename.'),
73
+ limit: z
74
+ .number()
75
+ .optional()
76
+ .default(25)
77
+ .describe('Maximum number of growing classes to report (default 25).'),
78
+ min_growth_count: z
79
+ .number()
80
+ .optional()
81
+ .default(50)
82
+ .describe('Only report classes whose net instance-count growth is at least this (default 50).'),
83
+ monotonic_only: z
84
+ .boolean()
85
+ .optional()
86
+ .default(false)
87
+ .describe('Report only classes that grew at EVERY step (default false: include grew-net too, flagged).'),
88
+ max_file_size_mb: z
89
+ .number()
90
+ .optional()
91
+ .default(900)
92
+ .describe('Per-file size ceiling (default 900) to avoid OOM.'),
93
+ }, async ({ paths, limit, min_growth_count, monotonic_only, max_file_size_mb, }) => {
94
+ try {
95
+ const steps = [];
96
+ for (const p of paths) {
97
+ let local;
98
+ let fetchedFrom = null;
99
+ try {
100
+ const r = resolveSnapshotPath(p);
101
+ local = r.localPath;
102
+ fetchedFrom = r.fetchedFrom;
103
+ }
104
+ catch (e) {
105
+ return errorResult(new Error(`Failed to resolve "${p}": ${e instanceof Error ? e.message : String(e)}`));
106
+ }
107
+ if (!fs.existsSync(local)) {
108
+ return errorResult(new Error(`File not found: ${local}`));
109
+ }
110
+ const sizeMB = fs.statSync(local).size / (1024 * 1024);
111
+ if (sizeMB > max_file_size_mb) {
112
+ return errorResult(new Error(`${p} is ${sizeMB.toFixed(0)} MB — exceeds max_file_size_mb (${max_file_size_mb}).`));
113
+ }
114
+ // Load sequentially and drop the graph before the next one so only
115
+ // one full graph is resident at a time (memory-safe for big heaps).
116
+ const snapshot = await getFullHeapFromFile(local);
117
+ const { hist, nodeCount, totalSize } = buildHistogram(snapshot);
118
+ steps.push({
119
+ label: fetchedFrom ?? p.replace(/^.*\//, ''),
120
+ hist,
121
+ nodeCount,
122
+ totalSize,
123
+ });
124
+ }
125
+ const n = steps.length;
126
+ const first = steps[0].hist;
127
+ const last = steps[n - 1].hist;
128
+ // Union of non-noise class keys.
129
+ const keys = new Set();
130
+ for (const s of steps) {
131
+ for (const k of s.hist.keys()) {
132
+ const sep = k.indexOf('::');
133
+ const type = k.slice(0, sep);
134
+ const name = k.slice(sep + 2);
135
+ if (!isNoiseClass(type, name))
136
+ keys.add(k);
137
+ }
138
+ }
139
+ const rows = [];
140
+ for (const k of keys) {
141
+ const counts = steps.map(s => s.hist.get(k)?.count ?? 0);
142
+ const sizes = steps.map(s => s.hist.get(k)?.selfSize ?? 0);
143
+ const netCount = counts[n - 1] - counts[0];
144
+ const netSize = sizes[n - 1] - sizes[0];
145
+ if (netCount < min_growth_count)
146
+ continue;
147
+ const trend = classifyTrend(counts);
148
+ if (monotonic_only && trend !== 'monotonic-up')
149
+ continue;
150
+ if (trend !== 'monotonic-up' && trend !== 'grew-net')
151
+ continue;
152
+ rows.push({ key: k, counts, netCount, netSize, trend });
153
+ }
154
+ // Monotonic growers first, then by net size delta.
155
+ rows.sort((a, b) => {
156
+ if (a.trend !== b.trend)
157
+ return a.trend === 'monotonic-up' ? -1 : 1;
158
+ return b.netSize - a.netSize;
159
+ });
160
+ const top = rows.slice(0, limit);
161
+ const lines = [
162
+ `## Sequence / Trend Analysis (${n} snapshots)`,
163
+ '',
164
+ ];
165
+ // Per-step heap totals.
166
+ const totalHeaders = ['Step', 'Snapshot', 'Nodes', 'Heap (self)'];
167
+ const totalRows = steps.map((s, i) => [
168
+ String(i + 1),
169
+ s.label.length > 40 ? '…' + s.label.slice(-39) : s.label,
170
+ formatNumber(s.nodeCount),
171
+ formatBytes(s.totalSize),
172
+ ]);
173
+ lines.push(markdownTable(totalHeaders, totalRows, new Set([2, 3])));
174
+ const heapNet = steps[n - 1].totalSize - steps[0].totalSize;
175
+ lines.push('', `Overall heap self-size ${heapNet >= 0 ? 'grew' : 'shrank'} by ${formatBytes(Math.abs(heapNet))} across the sequence.`, '');
176
+ if (top.length === 0) {
177
+ lines.push(`No classes grew by >= ${formatNumber(min_growth_count)} instances across the sequence. Heap looks flat-to-shrinking — no unbounded-growth signal.`);
178
+ return toolResult(lines.join('\n'));
179
+ }
180
+ lines.push('### Growing classes', '');
181
+ const headers = [
182
+ 'Class',
183
+ 'Type',
184
+ ...steps.map((_, i) => `#${i + 1}`),
185
+ 'Δ count',
186
+ 'Δ size',
187
+ 'Verdict',
188
+ ];
189
+ const rightCols = new Set();
190
+ for (let i = 2; i < headers.length - 1; i++)
191
+ rightCols.add(i);
192
+ const tableRows = top.map(r => {
193
+ const sep = r.key.indexOf('::');
194
+ const type = r.key.slice(0, sep);
195
+ const name = r.key.slice(sep + 2);
196
+ const verdict = r.trend === 'monotonic-up'
197
+ ? '↑ every step (LEAK signal)'
198
+ : 'grew net (noisy)';
199
+ return [
200
+ name.length > 36 ? name.slice(0, 33) + '…' : name,
201
+ type,
202
+ ...r.counts.map(c => formatNumber(c)),
203
+ `+${formatNumber(r.netCount)}`,
204
+ `${r.netSize >= 0 ? '+' : ''}${formatBytes(r.netSize)}`,
205
+ verdict,
206
+ ];
207
+ });
208
+ lines.push(markdownTable(headers, tableRows, rightCols));
209
+ // New-since-baseline classes (absent at step 1, present at step N).
210
+ const newClasses = [];
211
+ for (const k of keys) {
212
+ if (!first.has(k) && last.has(k)) {
213
+ const c = last.get(k)?.count ?? 0;
214
+ if (c >= min_growth_count) {
215
+ const sep = k.indexOf('::');
216
+ newClasses.push(`${k.slice(sep + 2)} (${formatNumber(c)})`);
217
+ }
218
+ }
219
+ }
220
+ if (newClasses.length > 0) {
221
+ lines.push('', '### New since baseline', '', newClasses.slice(0, 20).join(', ') +
222
+ (newClasses.length > 20
223
+ ? `, … +${newClasses.length - 20} more`
224
+ : ''));
225
+ }
226
+ // "heap number" is V8's node for a captured numeric value. It only
227
+ // appears when the snapshot was taken with numeric-value capture on
228
+ // (Chrome's captureNumericValue / the browser MCP's capture_numeric_value
229
+ // option). In that mode V8 emits one node per distinct number, which
230
+ // both ~3x inflates the graph and shows up here as a top "↑ every step"
231
+ // grower — a capture artifact, not a real leak. Flag it so it isn't
232
+ // mistaken for the leak signal.
233
+ if (top.some(r => r.key === 'number::heap number')) {
234
+ lines.push('', '> ⚠️ `heap number` is growing. This is almost always a **capture artifact** from taking snapshots with numeric-value capture enabled (one graph node per distinct number), not a real leak. Re-capture with numeric values OFF (browser MCP `capture_numeric_value: false`) for a ~3x smaller, faster, cleaner graph, and disregard `heap number` growth here.');
235
+ }
236
+ lines.push('', '_"↑ every step" is the strong unbounded-growth signal; "grew net (noisy)" often reflects GC timing or navigation and warrants a closer look before treating as a leak. Object-identity matching across snapshots is not available (node ids differ per capture) — to localize a specific growing collection, load the last snapshot and use `memlab_cache_analysis` / `memlab_event_listener_leaks` / `memlab_growth_signals`._');
237
+ return toolResult(lines.join('\n'));
238
+ }
239
+ catch (err) {
240
+ return errorResult(err);
241
+ }
242
+ });
243
+ }
244
+ //# sourceMappingURL=sequence-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence-analysis.js","sourceRoot":"","sources":["../../src/tools/sequence-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ export declare function registerServerStatus(server: McpServer): void;
12
+ //# sourceMappingURL=server-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-status.d.ts","sourceRoot":"","sources":["../../src/tools/server-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAIvE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsC5D"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import { listSnapshots, getCurrentHandle } from '../heap-state.js';
11
+ import { formatBytes, formatNumber, errorResult, textResult } from '../utils.js';
12
+ export function registerServerStatus(server) {
13
+ server.tool('memlab_server_status', 'Cheap liveness/health check: returns instantly with the server process RSS, uptime, and the resident snapshots. Use it to confirm the server is responsive (vs. stuck behind a heavy scan) and to watch RSS against the snapshot-size ceiling. Scan tools are time-budgeted (timeout_ms) so a heavy scan returns cleanly instead of wedging the server; if a call ever seems hung, this check should still answer immediately.', {}, async () => {
14
+ try {
15
+ const mem = process.memoryUsage();
16
+ const uptimeS = Math.round(process.uptime());
17
+ const all = listSnapshots();
18
+ const cur = getCurrentHandle();
19
+ const lines = [
20
+ '## memlab server status',
21
+ '',
22
+ `- Status: ready`,
23
+ `- Uptime: ${uptimeS}s`,
24
+ `- Process RSS: ${formatBytes(mem.rss)} (heapUsed ${formatBytes(mem.heapUsed)} / heapTotal ${formatBytes(mem.heapTotal)})`,
25
+ `- Resident snapshots: ${all.length}`,
26
+ ];
27
+ for (const m of all) {
28
+ lines.push(` ${m.handle === cur ? '→' : ' '} ${m.handle} — ${m.fileName}, ${formatBytes(m.totalSize)}, ${formatNumber(m.nodeCount)} nodes`);
29
+ }
30
+ if (all.length === 0) {
31
+ lines.push(' (none loaded — use memlab_load_snapshot)');
32
+ }
33
+ lines.push('', '_Tip: full-heap scan tools (search_nodes, find_by_property, global_variables) accept timeout_ms and return partial results rather than hanging. If RSS approaches your --max-old-space-size, unload snapshots with memlab_snapshots(action:"unload")._', '_Recovery: if a prior long/interrupted call left the server unresponsive (even trivial calls hang), starting a FRESH server instance fully recovers it — restart the MCP server and reload the snapshot._');
34
+ return textResult(lines.join('\n'));
35
+ }
36
+ catch (err) {
37
+ return errorResult(err);
38
+ }
39
+ });
40
+ }
41
+ //# sourceMappingURL=server-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-status.js","sourceRoot":"","sources":["../../src/tools/server-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAC,aAAa,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAC,MAAM,aAAa,CAAC;AAE/E,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,gaAAga,EACha,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG;gBACZ,yBAAyB;gBACzB,EAAE;gBACF,iBAAiB;gBACjB,aAAa,OAAO,GAAG;gBACvB,kBAAkB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG;gBAC1H,yBAAyB,GAAG,CAAC,MAAM,EAAE;aACtC,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CACjI,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAC3D,CAAC;YACD,KAAK,CAAC,IAAI,CACR,EAAE,EACF,wPAAwP,EACxP,2MAA2M,CAC5M,CAAC;YACF,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"shape-histogram.d.ts","sourceRoot":"","sources":["../../src/tools/shape-histogram.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA4BvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+H9D"}
1
+ {"version":3,"file":"shape-histogram.d.ts","sourceRoot":"","sources":["../../src/tools/shape-histogram.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAmCvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2L9D"}