memorydetective
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| prompts | {
"listChanged": true
} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| analyzeMemgraphA | [mg.memory] Run Pipeline: → |
| findCyclesA | [mg.memory] Extract just the ROOT CYCLE blocks from a |
| findRetainersA | [mg.memory] Walk the cycle forest from a |
| countAliveA | [mg.memory] Count how many times each class appears in a |
| diffMemgraphsA | [mg.memory] Compare a baseline |
| analyzeAbandonedMemoryA | [mg.memory] Compare two Pair with the verify-fix loop: Returns |
| cleanupTracesA | [ops] Triage and clean up Default-safe: Scope: restricted to Recursion boundary: the tool walks subdirectories looking for Use |
| classifyCycleA | [mg.memory] Match each ROOT CYCLE against a built-in catalog of 8 known antipatterns (TagIndexProjection cycle, ForEachState retention, Combine sink-store-self, Task-without-weak-self, NotificationCenter observer, viewmodel-wrapped-strong closure, UINavigationController host, _DictionaryStorage internal). Returns Pipeline: this is the killer tool — after the result, follow |
| analyzeHangsA | [mg.trace] Run |
| analyzeTimeProfileA | [mg.trace] Export the |
| listTraceDevicesA | [mg.discover] Run |
| listTraceTemplatesA | [mg.discover] Run |
| inspectTraceA | [mg.discover] Single-call orientation tool for |
| summarizeTraceA | [mg.synthesize] The trace-to-summary-card-in-one-call play. Chains |
| recordTimeProfileA | [mg.trace] Wrapper around |
| captureMemgraphA | [mg.memory] Wrapper around |
| bootAndLaunchForLeakInvestigationA | [mg.build] Single-call orchestration that runs |
| replayScenarioA | [mg.scenario] Drive the iOS Simulator through a sequence of UI actions (tap, swipe, wait, type) and optionally repeat the sequence N times to amplify a leak that only manifests after iteration. Tied to verify-fix: pair with captureScenarioState before/after to make leak reproductions deterministic. Soft dependency on |
| captureScenarioStateA | [mg.scenario] Composite snapshot: writes a |
| analyzeAnimationHitchesA | [mg.trace] Parse the |
| analyzeAllocationsB | [mg.trace] Parse the |
| analyzeAppLaunchA | [mg.trace] Parse the |
| analyzeNetworkActivityA | [mg.trace] Parse the |
| analyzeMemoryFootprintA | [mg.trace] Parse the |
| analyzeEnergyImpactA | [mg.trace] Parse the |
| analyzeLeakTimelineA | [mg.trace] Parse the |
| recordViaInstrumentsAppA | [mg.build] Open Instruments.app, prompt the user to record + save a .trace, then poll a watchDir for the new bundle and chain into inspectTrace. The macOS 26.x escape hatch: |
| analyzeMetricKitPayloadA | [mg.production] Parse Apple MetricKit |
| renderCycleGraphA | [mg.render] Read a |
| logShowA | [mg.log] Wrap |
| logStreamB | [mg.log] Wrap |
| detectLeaksInXCUITestA | [mg.ci] Build the workspace for testing, launch the test cycle, capture a baseline |
| detectLeaksInXCTestA | [mg.ci] Sibling to |
| reachableFromCycleA | [mg.memory] Cycle-scoped reachability + class counting. Answers questions like "how many |
| swiftGetSymbolDefinitionA | [mg.code] Find the file:line where a Swift symbol (class, struct, enum, protocol, func, var, etc.) is declared. Pre-scans |
| swiftFindSymbolReferencesA | [mg.code] Locates the symbol's declaration in |
| swiftGetSymbolsOverviewA | [mg.code] Cheap orientation: returns the top-level symbols (classes, structs, enums, protocols, free functions) declared in a Swift file via SourceKit-LSP's |
| swiftGetHoverInfoA | [mg.code] SourceKit-LSP |
| swiftSearchPatternA | [mg.code] Pure regex search over a file's contents — no SourceKit-LSP, no IndexStoreDB. Catches what LSP misses: closure capture lists ( |
| getInvestigationPlaybookA | [meta] Returns a versioned, declarative pipeline for a known investigation flow ( |
| verifyFixA | [mg.memory] Cycle-semantic diff. Classifies both Pipeline: this is the natural followup to |
| compareTracesByPatternA | [mg.trace][mg.ci] Trace-side counterpart to Pipeline: capture before/after |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| investigate-leak | Run the canonical 6-step memgraph-leak investigation: analyzeMemgraph → classifyCycle → reachableFromCycle → swiftSearchPattern → swiftGetSymbolDefinition → swiftFindSymbolReferences. |
| investigate-hangs | Diagnose main-thread hangs from a `.trace` recorded with the Time Profiler or Hangs template. |
| investigate-jank | Diagnose dropped frames from a `.trace` recorded with the Animation Hitches template. |
| investigate-launch | Diagnose cold/warm launch slowness from a `.trace` recorded with the App Launch template. |
| summarize-trace | Call `summarizeTrace` on the user-supplied .trace and present the markdown card. Surfaces hangs, hitches, time-profile hotspots, allocations, app launch, and cross-correlations in one pass. Use this as the FIRST step on any new .trace. |
| investigate-metrickit | Run the post-mortem flow on Apple MetricKit `.mxdiagnostic` payloads collected from real-device TestFlight / App Store builds. Calls `analyzeMetricKitPayload` to surface clustered crashes, hang hotspots, CPU / disk exceptions, then follows cross-tool chain hints into `findCycles` / `analyzeHangs` when the top frame matches a known shape. Use this when the user has `.mxdiagnostic` files, not a local repro. |
| verify-cycle-fix | Diff a before/after pair of `.memgraph` snapshots to confirm a fix actually closed the originally-classified cycle. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| SwiftUI .tag(...) closure-over-self cycle | SwiftUI .tag(...) closure-over-self cycle |
| SwiftUI _DictionaryStorage<…WeakBox<AnyLocationBase>> internal cycle | SwiftUI _DictionaryStorage<…WeakBox<AnyLocationBase>> internal cycle |
| SwiftUI ForEachState retained by tap-gesture closure | SwiftUI ForEachState retained by tap-gesture closure |
| Closure capturing `_viewModel.wrappedValue` strongly | Closure capturing `_viewModel.wrappedValue` strongly |
| UIViewControllerRepresentable + UINavigationController host cycle | UIViewControllerRepresentable + UINavigationController host cycle |
| Combine .sink/.assign closure capturing self via AnyCancellable | Combine .sink/.assign closure capturing self via AnyCancellable |
| Swift `Task { }` body strongly capturing self | Swift `Task { }` body strongly capturing self |
| NotificationCenter observer block capturing self | NotificationCenter observer block capturing self |
| Combine `.assign(to: \.x, on: self)` capturing self | Combine `.assign(to: \.x, on: self)` capturing self |
| Swift `Task { }` inside a SwiftUI View capturing self | Swift `Task { }` inside a SwiftUI View capturing self |
| NotificationCenter observer never deregistered | NotificationCenter observer never deregistered |
| `delegate` property declared without `weak` | `delegate` property declared without `weak` |
| Timer.scheduledTimer(target:selector:) retains its target | Timer.scheduledTimer(target:selector:) retains its target |
| CADisplayLink retains its target | CADisplayLink retains its target |
| UIGestureRecognizer / UIControl `addTarget` retains target | UIGestureRecognizer / UIControl `addTarget` retains target |
| `NSKeyValueObservation` token retains its change handler | `NSKeyValueObservation` token retains its change handler |
| URLSession retains its delegate strongly | URLSession retains its delegate strongly |
| SwiftUI `@EnvironmentObject` with back-reference to UIView/UIViewController | SwiftUI `@EnvironmentObject` with back-reference to UIView/UIViewController |
| `AsyncStream` continuation retains self via producer / onTermination | `AsyncStream` continuation retains self via producer / onTermination |
| `WKUserContentController.add(_:name:)` retains the handler | `WKUserContentController.add(_:name:)` retains the handler |
| DispatchSource event handler closure retains self | DispatchSource event handler closure retains self |
| RxSwift `DisposeBag` retains subscription closures capturing self | RxSwift `DisposeBag` retains subscription closures capturing self |
| Realm `NotificationToken` retains its change closure | Realm `NotificationToken` retains its change closure |
| Coordinator pattern: child holds parent strongly | Coordinator pattern: child holds parent strongly |
| CAAnimation retains its delegate (Apple's documented quirk) | CAAnimation retains its delegate (Apple's documented quirk) |
| Custom CALayer delegate pointing at non-UIView owner | Custom CALayer delegate pointing at non-UIView owner |
| NSFetchedResultsController retains its delegate | NSFetchedResultsController retains its delegate |
| @Observable class held as @State across modal presentation | @Observable class held as @State across modal presentation |
| NavigationPath retains every element ever pushed into it | NavigationPath retains every element ever pushed into it |
| `for await` over an infinite AsyncSequence pins self via the consuming Task | `for await` over an infinite AsyncSequence pins self via the consuming Task |
| `for await ... in NotificationCenter.notifications(named:)` retains self forever | `for await ... in NotificationCenter.notifications(named:)` retains self forever |
| Swift 6.2 `Observations { }` closure retains self | Swift 6.2 `Observations { }` closure retains self |
| WKScriptMessageHandler bridge: handler ↔ webview ↔ contentController cycle | WKScriptMessageHandler bridge: handler ↔ webview ↔ contentController cycle |
| UIViewController alive in heap with no parent/presenting nav link | UIViewController alive in heap with no parent/presenting nav link |
| @Observable mutated inside `body`, triggering infinite re-render and a heap-side closure chain | @Observable mutated inside `body`, triggering infinite re-render and a heap-side closure chain |
| SwiftData ModelContext retained by actor through DefaultSerialModelExecutor | SwiftData ModelContext retained by actor through DefaultSerialModelExecutor |
TDQS
Scored across 42 tools
Most tools are clearly distinct in purpose, but several memgraph-analysis tools (analyzeMemgraph, findCycles, classifyCycle, reachableFromCycle) overlap in theme and input, though they return different views. Descriptions are detailed enough to help an agent avoid misselection, but the boundary between some trace analyzers (e.g., analyzeAllocations vs analyzeMemoryFootprint) could still confuse.
All 42 tools follow a consistent camelCase convention with a clear verb-noun pattern (analyze*, capture*, list*, find*, etc.). The naming makes it easy to predict tool behavior from its name, and there are no mixed conventions or chaotic verb styles.
42 tools is far beyond the typical well-scoped range and even exceeds the 'heavy' threshold. The server covers many subdomains (leaks, traces, logs, code navigation, CI), but many analyzers could be consolidated into parameterized tools (e.g., a single analyzeTrace with a schema argument). The high count increases selection difficulty and cognitive load.
The tool surface covers the full investigation lifecycle: capture (captureMemgraph, recordTimeProfile, bootAndLaunchForLeakInvestigation), analysis (findCycles, analyzeHangs, analyzeAppLaunch), diffing/verification (diffMemgraphs, verifyFix, compareTracesByPattern), CI integration (detectLeaksInXCTest/UI), and even production diagnostics (analyzeMetricKitPayload). No obvious gaps for the stated purpose.