@memlab/mcp-server 2.0.0

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 (107) hide show
  1. package/README.md +285 -0
  2. package/bin/memlab-mcp.js +3 -0
  3. package/dist/heap-state.d.ts +14 -0
  4. package/dist/heap-state.d.ts.map +1 -0
  5. package/dist/heap-state.js +25 -0
  6. package/dist/heap-state.js.map +1 -0
  7. package/dist/index.d.ts +12 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +71 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/tools/aggregate-nodes.d.ts +12 -0
  12. package/dist/tools/aggregate-nodes.d.ts.map +1 -0
  13. package/dist/tools/aggregate-nodes.js +136 -0
  14. package/dist/tools/aggregate-nodes.js.map +1 -0
  15. package/dist/tools/class-histogram.d.ts +12 -0
  16. package/dist/tools/class-histogram.d.ts.map +1 -0
  17. package/dist/tools/class-histogram.js +94 -0
  18. package/dist/tools/class-histogram.js.map +1 -0
  19. package/dist/tools/closure-inspection.d.ts +12 -0
  20. package/dist/tools/closure-inspection.d.ts.map +1 -0
  21. package/dist/tools/closure-inspection.js +107 -0
  22. package/dist/tools/closure-inspection.js.map +1 -0
  23. package/dist/tools/detached-dom.d.ts +12 -0
  24. package/dist/tools/detached-dom.d.ts.map +1 -0
  25. package/dist/tools/detached-dom.js +53 -0
  26. package/dist/tools/detached-dom.js.map +1 -0
  27. package/dist/tools/dominator-subtree.d.ts +12 -0
  28. package/dist/tools/dominator-subtree.d.ts.map +1 -0
  29. package/dist/tools/dominator-subtree.js +77 -0
  30. package/dist/tools/dominator-subtree.js.map +1 -0
  31. package/dist/tools/duplicated-strings.d.ts +12 -0
  32. package/dist/tools/duplicated-strings.d.ts.map +1 -0
  33. package/dist/tools/duplicated-strings.js +78 -0
  34. package/dist/tools/duplicated-strings.js.map +1 -0
  35. package/dist/tools/eval.d.ts +12 -0
  36. package/dist/tools/eval.d.ts.map +1 -0
  37. package/dist/tools/eval.js +119 -0
  38. package/dist/tools/eval.js.map +1 -0
  39. package/dist/tools/find-by-property.d.ts +12 -0
  40. package/dist/tools/find-by-property.d.ts.map +1 -0
  41. package/dist/tools/find-by-property.js +77 -0
  42. package/dist/tools/find-by-property.js.map +1 -0
  43. package/dist/tools/find-nodes-by-class.d.ts +12 -0
  44. package/dist/tools/find-nodes-by-class.d.ts.map +1 -0
  45. package/dist/tools/find-nodes-by-class.js +38 -0
  46. package/dist/tools/find-nodes-by-class.js.map +1 -0
  47. package/dist/tools/for-each.d.ts +12 -0
  48. package/dist/tools/for-each.d.ts.map +1 -0
  49. package/dist/tools/for-each.js +185 -0
  50. package/dist/tools/for-each.js.map +1 -0
  51. package/dist/tools/get-node.d.ts +12 -0
  52. package/dist/tools/get-node.d.ts.map +1 -0
  53. package/dist/tools/get-node.js +51 -0
  54. package/dist/tools/get-node.js.map +1 -0
  55. package/dist/tools/get-property.d.ts +12 -0
  56. package/dist/tools/get-property.d.ts.map +1 -0
  57. package/dist/tools/get-property.js +88 -0
  58. package/dist/tools/get-property.js.map +1 -0
  59. package/dist/tools/get-references.d.ts +12 -0
  60. package/dist/tools/get-references.d.ts.map +1 -0
  61. package/dist/tools/get-references.js +61 -0
  62. package/dist/tools/get-references.js.map +1 -0
  63. package/dist/tools/get-referrers.d.ts +12 -0
  64. package/dist/tools/get-referrers.d.ts.map +1 -0
  65. package/dist/tools/get-referrers.js +61 -0
  66. package/dist/tools/get-referrers.js.map +1 -0
  67. package/dist/tools/global-variables.d.ts +12 -0
  68. package/dist/tools/global-variables.d.ts.map +1 -0
  69. package/dist/tools/global-variables.js +331 -0
  70. package/dist/tools/global-variables.js.map +1 -0
  71. package/dist/tools/largest-objects.d.ts +12 -0
  72. package/dist/tools/largest-objects.d.ts.map +1 -0
  73. package/dist/tools/largest-objects.js +32 -0
  74. package/dist/tools/largest-objects.js.map +1 -0
  75. package/dist/tools/load-snapshot.d.ts +12 -0
  76. package/dist/tools/load-snapshot.d.ts.map +1 -0
  77. package/dist/tools/load-snapshot.js +39 -0
  78. package/dist/tools/load-snapshot.js.map +1 -0
  79. package/dist/tools/object-shape.d.ts +12 -0
  80. package/dist/tools/object-shape.d.ts.map +1 -0
  81. package/dist/tools/object-shape.js +86 -0
  82. package/dist/tools/object-shape.js.map +1 -0
  83. package/dist/tools/reports.d.ts +12 -0
  84. package/dist/tools/reports.d.ts.map +1 -0
  85. package/dist/tools/reports.js +540 -0
  86. package/dist/tools/reports.js.map +1 -0
  87. package/dist/tools/retainer-trace.d.ts +12 -0
  88. package/dist/tools/retainer-trace.d.ts.map +1 -0
  89. package/dist/tools/retainer-trace.js +68 -0
  90. package/dist/tools/retainer-trace.js.map +1 -0
  91. package/dist/tools/search-nodes.d.ts +12 -0
  92. package/dist/tools/search-nodes.d.ts.map +1 -0
  93. package/dist/tools/search-nodes.js +85 -0
  94. package/dist/tools/search-nodes.js.map +1 -0
  95. package/dist/tools/snapshot-summary.d.ts +12 -0
  96. package/dist/tools/snapshot-summary.d.ts.map +1 -0
  97. package/dist/tools/snapshot-summary.js +73 -0
  98. package/dist/tools/snapshot-summary.js.map +1 -0
  99. package/dist/tools/stale-collections.d.ts +12 -0
  100. package/dist/tools/stale-collections.d.ts.map +1 -0
  101. package/dist/tools/stale-collections.js +97 -0
  102. package/dist/tools/stale-collections.js.map +1 -0
  103. package/dist/utils.d.ts +82 -0
  104. package/dist/utils.d.ts.map +1 -0
  105. package/dist/utils.js +220 -0
  106. package/dist/utils.js.map +1 -0
  107. package/package.json +58 -0
@@ -0,0 +1,119 @@
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 vm from 'node:vm';
12
+ import memlabCore from '@memlab/core';
13
+ const { utils } = memlabCore;
14
+ import { getSnapshot } from '../heap-state.js';
15
+ import { errorResult, textResult, serializeNodeSummary, serializeNodeDetail, formatBytes, formatNumber, markdownTable, isNodeWorthInspecting, filterLargestObjects, queryNodes, } from '../utils.js';
16
+ const MAX_OUTPUT_SIZE = 50 * 1024; // 50KB
17
+ function truncate(str, max) {
18
+ if (str.length <= max)
19
+ return str;
20
+ return str.slice(0, max) + '\n... [truncated, output exceeded 50KB]';
21
+ }
22
+ export function registerEval(server) {
23
+ server.tool('memlab_eval', 'Execute arbitrary JavaScript code against the loaded heap snapshot. ' +
24
+ 'The code runs in a sandboxed VM with access to `snapshot` (IHeapSnapshot), ' +
25
+ '`utils` (@memlab/core utils), and `helpers` (plugin utility functions). ' +
26
+ 'Assign your result to the `result` variable. ' +
27
+ 'No require/process/fs/network access. Read-only heap analysis only.', {
28
+ code: z
29
+ .string()
30
+ .describe('JavaScript code to execute. Must assign the output to a `result` variable. ' +
31
+ 'Available globals: snapshot (IHeapSnapshot), utils (@memlab/core utils with ' +
32
+ 'aggregateDominatorMetrics, isFiberNode, isDetachedDOMNode, etc.), ' +
33
+ 'helpers ({ serializeNodeSummary, serializeNodeDetail, formatBytes, formatNumber, ' +
34
+ 'markdownTable, isNodeWorthInspecting, filterLargestObjects, queryNodes }), ' +
35
+ 'and standard JS built-ins (Array, Object, Map, Set, JSON, Math, RegExp, console).'),
36
+ timeout_ms: z
37
+ .number()
38
+ .optional()
39
+ .default(30000)
40
+ .describe('Execution timeout in milliseconds (default 30000)'),
41
+ }, async ({ code, timeout_ms }) => {
42
+ try {
43
+ const snapshot = getSnapshot();
44
+ const consoleOutput = [];
45
+ const capturedConsole = {
46
+ log: (...args) => consoleOutput.push(args.map(String).join(' ')),
47
+ warn: (...args) => consoleOutput.push('[warn] ' + args.map(String).join(' ')),
48
+ error: (...args) => consoleOutput.push('[error] ' + args.map(String).join(' ')),
49
+ info: (...args) => consoleOutput.push('[info] ' + args.map(String).join(' ')),
50
+ };
51
+ const helpers = {
52
+ serializeNodeSummary,
53
+ serializeNodeDetail,
54
+ formatBytes,
55
+ formatNumber,
56
+ markdownTable,
57
+ isNodeWorthInspecting,
58
+ filterLargestObjects,
59
+ queryNodes,
60
+ };
61
+ const sandbox = {
62
+ snapshot,
63
+ utils,
64
+ helpers,
65
+ console: capturedConsole,
66
+ result: undefined,
67
+ // Standard JS globals
68
+ Array,
69
+ Object,
70
+ Map,
71
+ Set,
72
+ JSON,
73
+ Math,
74
+ RegExp,
75
+ String,
76
+ Number,
77
+ Boolean,
78
+ Date,
79
+ Error,
80
+ TypeError,
81
+ RangeError,
82
+ WeakMap,
83
+ WeakSet,
84
+ Symbol,
85
+ parseInt,
86
+ parseFloat,
87
+ isNaN,
88
+ isFinite,
89
+ Infinity,
90
+ NaN,
91
+ undefined,
92
+ };
93
+ const context = vm.createContext(sandbox);
94
+ const script = new vm.Script(code, { filename: 'memlab_eval' });
95
+ script.runInContext(context, { timeout: timeout_ms });
96
+ let output;
97
+ try {
98
+ output = JSON.stringify(sandbox.result, null, 2) ?? 'undefined';
99
+ }
100
+ catch {
101
+ output = String(sandbox.result);
102
+ }
103
+ output = truncate(output, MAX_OUTPUT_SIZE);
104
+ if (consoleOutput.length > 0) {
105
+ const consolePart = truncate(consoleOutput.join('\n'), MAX_OUTPUT_SIZE - output.length > 1024 ? 4096 : 1024);
106
+ output += '\n\n--- console output ---\n' + consolePart;
107
+ }
108
+ return textResult(output);
109
+ }
110
+ catch (err) {
111
+ if (err instanceof Error &&
112
+ err.message.includes('Script execution timed out')) {
113
+ return errorResult(new Error(`Execution timed out after ${timeout_ms}ms`));
114
+ }
115
+ return errorResult(err);
116
+ }
117
+ });
118
+ }
119
+ //# sourceMappingURL=eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/tools/eval.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 registerFindByProperty(server: McpServer): void;
12
+ //# sourceMappingURL=find-by-property.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-by-property.d.ts","sourceRoot":"","sources":["../../src/tools/find-by-property.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8E9D"}
@@ -0,0 +1,77 @@
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 { serializeNodeSummary, isNodeWorthInspecting, formatNodeSummaryTable, errorResult, textResult, } from '../utils.js';
13
+ export function registerFindByProperty(server) {
14
+ server.tool('memlab_find_by_property', 'Find all objects that have a specific property name (outgoing edge). Useful for identifying objects with React internals (__reactFiber$, __reactProps$), custom data structures, or framework-specific markers. Results sorted by retained size.', {
15
+ property_name: z
16
+ .string()
17
+ .describe('The property/edge name to search for (e.g., "__reactFiber$", "cache", "data")'),
18
+ edge_type: z
19
+ .string()
20
+ .optional()
21
+ .describe('Optional edge type filter (property, element, context, internal)'),
22
+ limit: z
23
+ .number()
24
+ .optional()
25
+ .default(20)
26
+ .describe('Maximum number of results (default 20)'),
27
+ }, async ({ property_name, edge_type, limit }) => {
28
+ try {
29
+ const snapshot = getSnapshot();
30
+ // Use prefix matching for names ending with $ (React dynamic suffixes)
31
+ const isPrefix = property_name.endsWith('$');
32
+ const results = [];
33
+ snapshot.nodes.forEach(node => {
34
+ if (!isNodeWorthInspecting(node))
35
+ return;
36
+ const hasProperty = node.references.some(edge => {
37
+ const edgeName = String(edge.name_or_index);
38
+ const nameMatch = isPrefix
39
+ ? edgeName.startsWith(property_name)
40
+ : edgeName === property_name;
41
+ if (!nameMatch)
42
+ return false;
43
+ if (edge_type && edge.type !== edge_type)
44
+ return false;
45
+ return true;
46
+ });
47
+ if (!hasProperty)
48
+ return;
49
+ // Insertion sort to keep top N by retained size
50
+ const size = node.retainedSize;
51
+ let inserted = false;
52
+ for (let i = 0; i < results.length; i++) {
53
+ if (size > results[i].retainedSize) {
54
+ results.splice(i, 0, node);
55
+ inserted = true;
56
+ break;
57
+ }
58
+ }
59
+ if (!inserted) {
60
+ results.push(node);
61
+ }
62
+ if (results.length > limit) {
63
+ results.length = limit;
64
+ }
65
+ });
66
+ const summaries = results.map(serializeNodeSummary);
67
+ if (summaries.length === 0) {
68
+ return textResult(`No objects found with property "${property_name}"${edge_type ? ` (edge type: ${edge_type})` : ''}`);
69
+ }
70
+ return textResult(`Found ${summaries.length} objects with property "${property_name}"${edge_type ? ` (edge type: ${edge_type})` : ''}\n\n${formatNodeSummaryTable(summaries)}`);
71
+ }
72
+ catch (err) {
73
+ return errorResult(err);
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=find-by-property.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-by-property.js","sourceRoot":"","sources":["../../src/tools/find-by-property.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 registerFindNodesByClass(server: McpServer): void;
12
+ //# sourceMappingURL=find-nodes-by-class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-nodes-by-class.d.ts","sourceRoot":"","sources":["../../src/tools/find-nodes-by-class.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAWvE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkChE"}
@@ -0,0 +1,38 @@
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 { filterLargestObjects, serializeNodeSummary, formatNodeSummaryTable, errorResult, textResult, } from '../utils.js';
13
+ export function registerFindNodesByClass(server) {
14
+ server.tool('memlab_find_nodes_by_class', 'Find heap objects by constructor/class name. Returns matching objects sorted by retained size.', {
15
+ class_name: z
16
+ .string()
17
+ .describe('The constructor or class name to search for'),
18
+ limit: z
19
+ .number()
20
+ .optional()
21
+ .default(20)
22
+ .describe('Maximum number of results (default 20)'),
23
+ }, async ({ class_name, limit }) => {
24
+ try {
25
+ const snapshot = getSnapshot();
26
+ const nodes = filterLargestObjects(snapshot, node => node.name === class_name && node.type === 'object', limit);
27
+ const summaries = nodes.map(serializeNodeSummary);
28
+ if (summaries.length === 0) {
29
+ return textResult(`No objects found with class "${class_name}"`);
30
+ }
31
+ return textResult(`Found ${summaries.length} "${class_name}" objects\n\n${formatNodeSummaryTable(summaries)}`);
32
+ }
33
+ catch (err) {
34
+ return errorResult(err);
35
+ }
36
+ });
37
+ }
38
+ //# sourceMappingURL=find-nodes-by-class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-nodes-by-class.js","sourceRoot":"","sources":["../../src/tools/find-nodes-by-class.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,CAAC,IAAI,CACT,4BAA4B,EAC5B,gGAAgG,EAChG;QACE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,CAAC,6CAA6C,CAAC;QAC1D,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,wCAAwC,CAAC;KACtD,EACD,KAAK,EAAE,EAAC,UAAU,EAAE,KAAK,EAAC,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,oBAAoB,CAChC,QAAQ,EACR,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAC1D,KAAK,CACN,CAAC;YACF,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,UAAU,CAAC,gCAAgC,UAAU,GAAG,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,UAAU,CACf,SAAS,SAAS,CAAC,MAAM,KAAK,UAAU,gBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAC5F,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -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 registerForEach(server: McpServer): void;
12
+ //# sourceMappingURL=for-each.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"for-each.d.ts","sourceRoot":"","sources":["../../src/tools/for-each.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA0BvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6MvD"}
@@ -0,0 +1,185 @@
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 vm from 'node:vm';
12
+ import memlabCore from '@memlab/core';
13
+ const { utils } = memlabCore;
14
+ import { getSnapshot } from '../heap-state.js';
15
+ import { errorResult, textResult, serializeNodeSummary, serializeNodeDetail, formatBytes, formatNumber, markdownTable, isNodeWorthInspecting, filterLargestObjects, queryNodes, } from '../utils.js';
16
+ const MAX_OUTPUT_SIZE = 50 * 1024; // 50KB
17
+ function truncate(str, max) {
18
+ if (str.length <= max)
19
+ return str;
20
+ return str.slice(0, max) + '\n... [truncated, output exceeded 50KB]';
21
+ }
22
+ export function registerForEach(server) {
23
+ server.tool('memlab_for_each', 'Structured map/filter/reduce over all heap nodes. ' +
24
+ 'Provide a filter predicate to select nodes, an optional map to transform them, ' +
25
+ 'and an optional reduce to aggregate results. ' +
26
+ 'All code strings receive `node` (for filter/map) or `acc, item` (for reduce), ' +
27
+ 'plus `utils` and `helpers` in scope. ' +
28
+ 'Returns an array of mapped results (capped at `limit`) or the reduced value.', {
29
+ filter_code: z
30
+ .string()
31
+ .describe('JS expression or function body: receives `node` (IHeapNode), return true to include. ' +
32
+ 'Example: "node.type === \'closure\' && node.retainedSize > 1048576"'),
33
+ map_code: z
34
+ .string()
35
+ .optional()
36
+ .describe('JS expression or function body: receives `node` (IHeapNode), return transformed value. ' +
37
+ 'Default: serializes node to NodeSummary. ' +
38
+ 'Example: "({ id: node.id, name: node.name, retained: node.retainedSize })"'),
39
+ reduce_code: z
40
+ .string()
41
+ .optional()
42
+ .describe('JS expression or function body: receives `acc` (accumulator) and `item` (mapped value), ' +
43
+ 'return new accumulator. If omitted, returns array of mapped results. ' +
44
+ 'Example: "acc + item.retained"'),
45
+ initial_value: z
46
+ .string()
47
+ .optional()
48
+ .describe('JSON string for the reduce initial accumulator value. ' +
49
+ 'Default: "[]" when reduce_code is present, ignored otherwise. ' +
50
+ 'Example: "0" or "{}"'),
51
+ limit: z
52
+ .number()
53
+ .optional()
54
+ .default(100)
55
+ .describe('Max results when not reducing (default 100)'),
56
+ timeout_ms: z
57
+ .number()
58
+ .optional()
59
+ .default(30000)
60
+ .describe('Execution timeout in milliseconds (default 30000)'),
61
+ }, async ({ filter_code, map_code, reduce_code, initial_value, limit, timeout_ms, }) => {
62
+ try {
63
+ const snapshot = getSnapshot();
64
+ const helpers = {
65
+ serializeNodeSummary,
66
+ serializeNodeDetail,
67
+ formatBytes,
68
+ formatNumber,
69
+ markdownTable,
70
+ isNodeWorthInspecting,
71
+ filterLargestObjects,
72
+ queryNodes,
73
+ };
74
+ const sandbox = {
75
+ snapshot,
76
+ utils,
77
+ helpers,
78
+ // Standard JS globals
79
+ Array,
80
+ Object,
81
+ Map,
82
+ Set,
83
+ JSON,
84
+ Math,
85
+ RegExp,
86
+ String,
87
+ Number,
88
+ Boolean,
89
+ Date,
90
+ Error,
91
+ TypeError,
92
+ RangeError,
93
+ WeakMap,
94
+ WeakSet,
95
+ Symbol,
96
+ parseInt,
97
+ parseFloat,
98
+ isNaN,
99
+ isFinite,
100
+ Infinity,
101
+ NaN,
102
+ undefined,
103
+ // Internal: will be set by the orchestration script
104
+ __filter: null,
105
+ __map: null,
106
+ __reduce: null,
107
+ __result: undefined,
108
+ };
109
+ const context = vm.createContext(sandbox);
110
+ // Compile filter function
111
+ const filterScript = new vm.Script(`__filter = (function(node) { return (${filter_code}); });`, { filename: 'memlab_for_each:filter' });
112
+ filterScript.runInContext(context, { timeout: 5000 });
113
+ // Compile map function
114
+ if (map_code) {
115
+ const mapScript = new vm.Script(`__map = (function(node) { return (${map_code}); });`, { filename: 'memlab_for_each:map' });
116
+ mapScript.runInContext(context, { timeout: 5000 });
117
+ }
118
+ else {
119
+ const defaultMapScript = new vm.Script(`__map = (function(node) { return helpers.serializeNodeSummary(node); });`, { filename: 'memlab_for_each:default_map' });
120
+ defaultMapScript.runInContext(context, { timeout: 5000 });
121
+ }
122
+ // Compile reduce function if provided
123
+ if (reduce_code) {
124
+ const reduceScript = new vm.Script(`__reduce = (function(acc, item) { return (${reduce_code}); });`, { filename: 'memlab_for_each:reduce' });
125
+ reduceScript.runInContext(context, { timeout: 5000 });
126
+ }
127
+ // Build and run the iteration logic
128
+ const isReducing = reduce_code != null;
129
+ const initVal = initial_value ?? (isReducing ? '[]' : undefined);
130
+ let iterationCode;
131
+ if (isReducing) {
132
+ iterationCode = `
133
+ (function() {
134
+ var acc = ${initVal};
135
+ snapshot.nodes.forEach(function(node) {
136
+ if (__filter(node)) {
137
+ var item = __map(node);
138
+ acc = __reduce(acc, item);
139
+ }
140
+ });
141
+ __result = acc;
142
+ })();
143
+ `;
144
+ }
145
+ else {
146
+ iterationCode = `
147
+ (function() {
148
+ var results = [];
149
+ var count = 0;
150
+ var limit = ${limit};
151
+ snapshot.nodes.forEach(function(node) {
152
+ if (count >= limit) return;
153
+ if (__filter(node)) {
154
+ results.push(__map(node));
155
+ count++;
156
+ }
157
+ });
158
+ __result = results;
159
+ })();
160
+ `;
161
+ }
162
+ const iterScript = new vm.Script(iterationCode, {
163
+ filename: 'memlab_for_each:iterate',
164
+ });
165
+ iterScript.runInContext(context, { timeout: timeout_ms });
166
+ let output;
167
+ try {
168
+ output = JSON.stringify(sandbox.__result, null, 2) ?? 'undefined';
169
+ }
170
+ catch {
171
+ output = String(sandbox.__result);
172
+ }
173
+ output = truncate(output, MAX_OUTPUT_SIZE);
174
+ return textResult(output);
175
+ }
176
+ catch (err) {
177
+ if (err instanceof Error &&
178
+ err.message.includes('Script execution timed out')) {
179
+ return errorResult(new Error(`Execution timed out after ${timeout_ms}ms`));
180
+ }
181
+ return errorResult(err);
182
+ }
183
+ });
184
+ }
185
+ //# sourceMappingURL=for-each.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"for-each.js","sourceRoot":"","sources":["../../src/tools/for-each.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 registerGetNode(server: McpServer): void;
12
+ //# sourceMappingURL=get-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-node.d.ts","sourceRoot":"","sources":["../../src/tools/get-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAWvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4CvD"}
@@ -0,0 +1,51 @@
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 { serializeNodeDetail, formatBytes, formatNumber, errorResult, textResult, } from '../utils.js';
13
+ export function registerGetNode(server) {
14
+ server.tool('memlab_get_node', 'Look up a heap node by its numeric ID. Returns full details including size, type, detachment status, dominator, location, and string value if applicable.', {
15
+ node_id: z.number().describe('The numeric ID of the heap node'),
16
+ }, async ({ node_id }) => {
17
+ try {
18
+ const snapshot = getSnapshot();
19
+ const node = snapshot.getNodeById(node_id);
20
+ if (!node) {
21
+ return errorResult(`Node with id ${node_id} not found`);
22
+ }
23
+ const d = serializeNodeDetail(node);
24
+ const lines = [
25
+ `**ID:** @${d.id}`,
26
+ `**Name:** ${d.name}`,
27
+ `**Type:** ${d.type}`,
28
+ `**Self Size:** ${formatBytes(d.self_size)}`,
29
+ `**Retained Size:** ${formatBytes(d.retained_size)}`,
30
+ `**Edges Out:** ${formatNumber(d.edge_count)}`,
31
+ `**Referrers:** ${formatNumber(d.referrer_count)}`,
32
+ `**Detached:** ${d.is_detached ? 'Yes' : 'No'}`,
33
+ `**Dominator:** ${d.dominator_id != null ? `@${d.dominator_id}` : 'none'}`,
34
+ ];
35
+ if (d.location) {
36
+ lines.push(`**Location:** script ${d.location.script_id}, line ${d.location.line}, col ${d.location.column}`);
37
+ }
38
+ if (d.string_value !== undefined) {
39
+ const val = d.string_value.length > 200
40
+ ? d.string_value.slice(0, 200) + '...'
41
+ : d.string_value;
42
+ lines.push(`**String Value:** "${val}"`);
43
+ }
44
+ return textResult(lines.join('\n'));
45
+ }
46
+ catch (err) {
47
+ return errorResult(err);
48
+ }
49
+ });
50
+ }
51
+ //# sourceMappingURL=get-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-node.js","sourceRoot":"","sources":["../../src/tools/get-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,2JAA2J,EAC3J;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;KAChE,EACD,KAAK,EAAE,EAAC,OAAO,EAAC,EAAE,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,WAAW,CAAC,gBAAgB,OAAO,YAAY,CAAC,CAAC;YAC1D,CAAC;YACD,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,KAAK,GAAG;gBACZ,YAAY,CAAC,CAAC,EAAE,EAAE;gBAClB,aAAa,CAAC,CAAC,IAAI,EAAE;gBACrB,aAAa,CAAC,CAAC,IAAI,EAAE;gBACrB,kBAAkB,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;gBAC5C,sBAAsB,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE;gBACpD,kBAAkB,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;gBAC9C,kBAAkB,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE;gBAClD,iBAAiB,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC/C,kBAAkB,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE;aAC3E,CAAC;YACF,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CACR,wBAAwB,CAAC,CAAC,QAAQ,CAAC,SAAS,UAAU,CAAC,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAClG,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,GAAG,GACP,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,GAAG;oBACzB,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;oBACtC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,sBAAsB,GAAG,GAAG,CAAC,CAAC;YAC3C,CAAC;YACD,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"}
@@ -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 registerGetProperty(server: McpServer): void;
12
+ //# sourceMappingURL=get-property.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-property.d.ts","sourceRoot":"","sources":["../../src/tools/get-property.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmG3D"}