# io.github.carloshpdoc/memorydetective (npm · memorydetective)

iOS leak/perf debugging via MCP: memgraph cycles, .trace analysis, SourceKit-LSP bridging.

- Trust score: 59/100 (low)
- Change this week: +35
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `memorydetective`: 59/100 (this document), [markdown](https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective.md), [page](https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective)

## Channel facts

- Registry: `npm`
- Package: `memorydetective`
- Version: `1.18.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 87/100
  - No malware found by supply-chain analysis.
  - Only part of the dependency tree could be resolved (107 of 111), so this covers what we could see, not the whole tree.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (107 of 111), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 70 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 43/100
  - 14% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 14245 tokens (~182/item across 78 items; 42 tools + 36 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 98/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 95% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### Claude

```bash
claude mcp add carloshpdoc-memorydetective -- npx -y memorydetective
```

### Codex

```bash
codex mcp add carloshpdoc-memorydetective -- npx -y memorydetective
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "carloshpdoc-memorydetective": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "memorydetective"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add carloshpdoc-memorydetective --command npx --arg -y --arg memorydetective
```

### Hermes

```yaml
mcp_servers:
  carloshpdoc-memorydetective:
    command: "npx"
    args: ["-y", "memorydetective"]
```

### Other

```json
{
  "mcpServers": {
    "carloshpdoc-memorydetective": {
      "command": "npx",
      "args": [
        "-y",
        "memorydetective"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 59, +36)

- [security regression] Provenance: unverified → fail
- [security improvement] Known CVEs: unverified → partial
- [security improvement] Install scripts: unverified → pass
- [security improvement] Malware scan: unverified → pass
- [security] Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- [functional regression] Capabilities: pass → unverified
- [functional improvement] Schema quality: unverified → good
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] Dependency health: unverified → partial
- [functional improvement] License: unverified → pass
- [functional] Licence: Apache-2.0

### 2026-08-01 (score 23, +5)

- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [functional improvement] MCP protocol: unverified → pass

### 2026-07-31 (score 18, −25)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-28 (score 43, +19)

- [functional improvement] Schema quality: unverified → 14
- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Schema quality: unverified
- [functional] First check of Tool coverage: 95
- [functional] First check of Schema quality: fail
- [functional] First check of Schema quality: fail

### 2026-07-27 (score 24)

First indexed and scored.

## MCP tools (42)

### `analyzeMemgraph` (~510 tokens)

Analyze a .memgraph file

[mg.memory] Run `leaks(1)` against a `.memgraph` file (exported from Xcode Memory Graph Debugger) and return a structured summary: header info, totals, top-level ROOT CYCLE blocks with chain length, plain-English diagnosis. Set `fullChains: true` to also include the full nested retain forest.

Pipeline: → `classifyCycle` (named-antipattern + fix hint) → `reachableFromCycle` (scope blame to a single root). The response includes `suggestedNextCalls` so the agent can chain without re-reasoning.

Input parameters:

- `fullChains` (boolean): When true, include the full nested retain chains in the response. Default false returns only top-level ROOT CYCLE summaries to keep payloads small.
- `maxClassesInChain` (integer): Cap on how many unique class names to surface per cycle's `classesInChain` array. Default 10, enough to identify app-level types without flooding the response.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `path` (string, required): Absolute path to a `.memgraph` file (export from Xcode Memory Graph Debugger).
- `referenceTreeTopN` (integer): When `leakCount` is 0 (the typical abandoned-memory case), also run `leaks --referenceTree --groupByType --noContent` and surface the top N classes by live instance count in `abandonedMemoryTop[]`. S…
- `verbosity` (string): Class-name verbosity. `compact` (default) drops module prefixes, collapses nested SwiftUI ModifiedContent into `+N modifiers`, and truncates deep generics with a hash placeholder. `normal` keeps more…

### `findCycles` (~166 tokens)

Find ROOT CYCLE blocks in a .memgraph

[mg.memory] Extract just the ROOT CYCLE blocks from a `.memgraph` as flattened chains (depth + edge + retainKind + className + address). Optionally filter to cycles touching a specific class name (substring match). Use this when you want to inspect chains without the noise of standalone leaks.

Input parameters:

- `className` (string): Optional substring filter — only return cycles where this class name appears in the chain (e.g. "DetailViewModel").
- `maxDepth` (integer): Truncate chains beyond this depth (default 10).
- `path` (string, required): Absolute path to a `.memgraph` file.
- `verbosity` (string): Class-name verbosity. `compact` shortens SwiftUI generic names aggressively; `full` returns demangled names verbatim.

### `findRetainers` (~316 tokens)

Find what retains a class

[mg.memory] Walk the cycle forest from a `.memgraph` and return every retain chain that ends in a node whose className contains the given substring. Useful for answering "who is keeping <class> alive?". Returns paths from a top-level node down to the matching node.

Input parameters:

- `className` (string, required): Class name (or substring) to find retainers for, e.g. "DetailViewModel".
- `includeReferenceTree` (boolean): v1.12+. When true, also run `leaks --debug=stacks --debug='<className>$'` to surface per-instance allocation stacks aggregated by call-stack fingerprint. Required on memgraphs where `leakCount: 0` an…
- `maxResults` (integer): Cap on how many retain chains to return (default 10).
- `path` (string, required): Absolute path to a `.memgraph` file.

### `countAlive` (~663 tokens)

Count instances by class

[mg.memory] Count how many times each class appears in a `.memgraph`'s leaked nodes. Provide `className` (substring) for a single number, or omit it to get the top N most-leaked classes. Use this to confirm whether a fix actually reduced instance counts.

Input parameters:

- `additionalNoisePatterns` (array): v1.17 B-10. Extra regex patterns (one per string) added to the noise filter. Useful when your app's noise classes are not in the curated list (e.g. third-party SDK collection storage that scales with…
- `className` (string): Optional class name (substring). When provided, only that class's count is returned. When omitted, all class counts are returned.
- `excludeFrameworkNoise` (boolean): v1.17 B-10. When `includeReferenceTree: true`, populates `actionableCounts[]` with the framework-noise classes filtered out (NSMutableDictionary, CFString, __DATA __bss, dispatch_queue_t, etc.). Set…
- `includeReferenceTree` (boolean): v1.12+. When true, also parse `leaks --referenceTree --groupByType --noContent` output and surface heap-wide instance counts alongside the cycle-side counts. Required to find classes on memgraphs whe…
- `noiseAuditMode` (boolean): v1.17 B-10. When true, returns an extra `noiseAudit[]` field listing each class that was filtered out, with the matching reason ('default-list', 'additional-pattern', or 'kept-by-unsuppress'). Lets t…
- `path` (string, required): Absolute path to a `.memgraph` file.
- `sortBy` (string): v1.14+. Ranks the topN by either instance count (default, preserves v1.13 behavior) or total bytes (FLEX's 'Size' sort). totalBytes is `count * instanceSizeBytes` and is the right rank for 'where is…
- `topN` (integer): When `className` is omitted, return the top N most-leaked classes (default 20).
- `unsuppressClassPatterns` (array): v1.17 B-10. Regex patterns that override the noise filter. Use when the default filter false-positives an actionable class (e.g. your app's `NSMutableDictionary` subclass is the actual leak site, or…

### `diffMemgraphs` (~251 tokens)

Diff two memgraph snapshots

[mg.memory] Compare a baseline `.memgraph` (`before`) against a comparison `.memgraph` (`after`). Returns total leak/byte deltas, classes whose counts increased or decreased, and ROOT CYCLE signatures bucketed into newInAfter / goneFromBefore / persisted. The killer feature for verifying that a fix actually worked.

Input parameters:

- `after` (string, required): Absolute path to the comparison `.memgraph` file.
- `before` (string, required): Absolute path to the baseline `.memgraph` file.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…

### `analyzeAbandonedMemory` (~590 tokens)

Diff reference-tree class counts and classify abandoned-memory shape

[mg.memory] Compare two `.memgraph` snapshots on heap reference-tree class counts (NOT cycle list) and classify each class's growth shape. Surfaces the family of bugs the cycle-only `diffMemgraphs` misses: orphaned KVO observers, never-removed NotificationCenter handlers, caches that never evict, singleton-retained payloads, and the long tail of `unknown-growth` worth manual inspection.

Pair with the verify-fix loop: `captureScenarioState({label:'before'})` -> ship fix -> `captureScenarioState({label:'after'})` -> `analyzeAbandonedMemory(beforePath, afterPath)`. Validated end-to-end on the notelet investigation where AVPlayerItem went 342 to 0 across a fix that was invisible in standard `leaks` output (leakCount: 0 both sides).

Returns `growthByClass[]` ranked by absolute delta, each entry tagged with `classification` (kvo-observer-orphaned, notificationcenter-observer-leaked, cache-too-aggressive, singleton-retains-payload, unknown-growth) + `confidence` tier + `hint`. The classifier escalates large co-occurrence growth: if NSKeyValueObservance grew, other large-delta classes are assumed to be the observed types being retained, classified as `kvo-observer-orphaned` with confidence scaling by delta size.

Input parameters:

- `afterPath` (string, required): Absolute path to the post-fix `.memgraph` (the AFTER snapshot). Same workflow as `beforePath`, after applying the candidate fix.
- `beforePath` (string, required): Absolute path to the baseline `.memgraph` (the BEFORE snapshot). Use `captureScenarioState({ label: 'before' })` to produce one in the standard verify-fix flow.
- `classFilter` (string): Optional substring filter. When set, only classes whose name contains this substring are included in the response. Useful for verifying a specific class went to baseline without seeing the surroundin…
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Cap on `growthByClass[]` length. Default 25, max 200. Classes are ranked by absolute instance-count delta descending.

### `cleanupTraces` (~577 tokens)

Preview and delete `.trace` bundles under TRACE_ROOT

[ops] Triage and clean up `.trace` bundles produced by `recordTimeProfile`. Each bundle is typically tens to hundreds of MB; after a few sessions the trace root fills up fast and v1.8 had no built-in cleanup.

\**Default-safe:** `dryRun: true` by default. The tool returns the list of candidates with `path`, `sizeMB`, and `ageDays` (sorted oldest-first) but deletes nothing. Pass `dryRun: false` only when the user has reviewed the candidates and authorized deletion.

\**Scope:** restricted to `MEMORYDETECTIVE_TRACE_ROOT` by default. To clean up an arbitrary directory, pass `root: <path>` AND set `MEMORYDETECTIVE_ALLOW_EXTERNAL_CLEANUP=1` in the env. Without the env var the tool returns `ok: false` with the failure reason and deletes nothing; destructive disk operations outside the configured boundary are default-deny.

\**Recursion boundary:** the tool walks subdirectories looking for `*.trace` directories, but stops at the `.trace` boundary (does NOT descend INTO bundles). xctrace writes structured content inside (Run1, Form1.template, etc.) that must not be treated as nested bundles.

Use `olderThanDays: N` to keep recent traces and only target stale ones (e.g. older than 7 days). Omit to consider all bundles regardless of age.

Input parameters:

- `dryRun` (boolean): When `true` (default), the tool returns the list of candidates without deleting. Pass `false` to actually delete. The default-to-true means an accidental call previews instead of destroying.
- `olderThanDays` (number): Only consider `.trace` bundles whose modification time is older than this many days. Omit to consider all traces under the root regardless of age.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `root` (string): Directory to scan. Defaults to `MEMORYDETECTIVE_TRACE_ROOT`. If the resolved path is outside the configured trace root, the tool requires `MEMORYDETECTIVE_ALLOW_EXTERNAL_CLEANUP=1` in the environment…

### `classifyCycle` (~176 tokens)

Classify ROOT CYCLEs against known patterns

[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 `patternId`, `confidence`, and a `fixHint` per cycle.

Pipeline: this is the killer tool — after the result, **follow `suggestedNextCalls`** which pre-translates each match to a Swift regex (`swiftSearchPattern`) + the captured class name (`swiftGetSymbolDefinition`). Discovery is data, not inference.

Input parameters:

- `maxResults` (integer): Cap on classifications returned (default 20).
- `path` (string, required): Absolute path to a `.memgraph` file.

### `analyzeHangs` (~808 tokens)

Analyze potential hangs from a .trace bundle

[mg.trace] Run `xcrun xctrace export` against a `.trace` bundle for the `potential-hangs` schema and return aggregated stats (Hang vs Microhang counts, longest, average, total duration) plus the top N longest hangs sorted by duration. Use `minDurationMs: 250` to filter to user-visible hangs only. Pass `topFramesByHangStartNs: { '<startNs>': '<topFrame>' }` to enrich each top hang with a `mainThreadViolations[]` field that classifies the kind of work blocking the main thread (sync-io, db-lock, network, lock-contention). The map keys are stringified `startNs` values; the typical pipeline is to call `analyzeTimeProfile` separately on the same trace, correlate samples to the hang windows by timestamp, then re-call `analyzeHangs` with the resulting map.

Input parameters:

- `includeStackClassification` (boolean): v1.12+. When true, analyzeHangs internally exports the `time-profile` schema in parallel with `potential-hangs`, correlates samples to hang windows by timestamp, picks the dominant top frame per hang…
- `minDurationMs` (number): Filter out hangs shorter than this duration in milliseconds (default 0, include all). Use 250 to focus on 'real' hangs only.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `timeRangeMs` (object): Optional time-window filter. Only hangs whose `startNs` falls within `[startMs, endMs]` (milliseconds since recording start) are included. Use this to answer 'what hangs happened between t=2s and t=7…
- `topFramesByHangStartNs` (object): Optional supplemental map from a hang's `startNs` (as a string) to the top frame seen during that hang. When provided, each matching hang in `top[]` is enriched with `mainThreadViolations[]` that cat…
- `topN` (integer): Return the top N longest hangs in the response (default 10).
- `tracePath` (string, required): Absolute path to a `.trace` bundle (output of `xctrace record` with the Time Profiler or Hangs template).

### `analyzeTimeProfile` (~256 tokens)

Analyze a Time Profiler trace

[mg.trace] Export the `time-profile` schema from a `.trace` bundle and return top symbols by sample count. Note: heavy/unsymbolicated traces may crash xctrace export — when that happens, the tool returns a `notice` field with workarounds (open in Instruments first to symbolicate, or re-record shorter).

Input parameters:

- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N hottest stacks by sample count (default 20).
- `tracePath` (string, required): Absolute path to a `.trace` bundle.

### `listTraceDevices` (~91 tokens)

List physical devices and simulators

[mg.discover] Run `xcrun xctrace list devices` and return parsed devices/simulators with their UDIDs. The LLM should call this before `recordTimeProfile` to discover the right UDID without asking the user. Set `includeOffline: true` to include disconnected devices.

Input parameters:

- `includeOffline` (boolean): Include devices listed under "Devices Offline" (default false).

### `listTraceTemplates` (~63 tokens)

List xctrace recording templates

[mg.discover] Run `xcrun xctrace list templates` and return parsed standard + custom templates. Useful when picking a template name for `recordTimeProfile` (e.g. "Time Profiler", "Animation Hitches", "Allocations").

### `inspectTrace` (~218 tokens)

Inspect a .trace bundle's TOC + suggest analyzers

[mg.discover] Single-call orientation tool for `.trace` bundles. Runs `xcrun xctrace export --xpath '/trace-toc/run'` and returns the schemas present (potential-hangs, animation-hitches, time-profile, allocations, app-launch, ...), their row counts, the device model, the OS version, the template name, the recording timestamp, and a `suggestedNextCalls[]` array mapping each populated schema to its matching `analyze*` tool with pre-populated args. Use this as the FIRST call when handed a `.trace` so you do not have to chain 5 analyzers blindly. Empty traces return `schemas: []` with a diagnosis pointing at Instruments.app for manual triage. Fallback path: when `/trace-toc/run` returns non-zero, retries with `/trace-toc` (older xctrace versions).

Input parameters:

- `tracePath` (string, required): Absolute path to a `.trace` bundle (output of `xcrun xctrace record` or Instruments).

### `summarizeTrace` (~345 tokens)

Single-call cross-schema summary card for a .trace bundle

[mg.synthesize] The trace-to-summary-card-in-one-call play. Chains `inspectTrace` + the matching `analyze*` tools (potential-hangs, animation-hitches, time-profile, allocations, app-launch) and returns BOTH a structured per-area result AND a pre-rendered compact markdown card (< 10 KB at default settings). Use this as the FIRST call when handed a `.trace` if you want one synthesis pass instead of chaining 5-6 analyzers manually. The markdown card carries a 1-sentence headline naming the biggest user-impact finding, then per-area sub-sections, then `suggestedNextCalls[]` for drilling in. Empty schemas are suppressed from the card to reduce noise. Failed analyzers (e.g. xctrace SIGSEGV on time-profile) surface inline with their workaround notice. Pass `verbose: true` to expand each section's top-N from 5 to 15+. Pass `focus: "hangs" | "hitches" | "allocations" | "launch"` to bias the summary toward a specific area.

Input parameters:

- `focus` (string): When set to a specific area, the summary card emphasizes that area and downplays others. Useful for piping into more focused agent loops. Default `all`.
- `tracePath` (string, required): Absolute path to a `.trace` bundle (output of `xcrun xctrace record` or Instruments).
- `verbose` (boolean): When true, the markdown card includes the full top-N per area (15+ rows per section) instead of the default 5. Trade-off: card grows from <10 KB to potentially 30+ KB.

### `recordTimeProfile` (~332 tokens)

Record a Time Profiler trace

[mg.trace] Wrapper around `xcrun xctrace record`. Capture a `.trace` bundle from a running app on a device or simulator. Required: exactly 1 of `deviceId`/`simulatorId`, exactly 1 of `attachAppName`/`attachPid`/`launchBundleId`, an `output` path ending in `.trace`. Defaults: template = "Time Profiler", durationSec = 90.

Input parameters:

- `attachAppName` (string): Attach to a running app by name (e.g. "DemoApp"). Mutually exclusive with `attachPid` and `launchBundleId`.
- `attachPid` (integer): Attach by PID. Mutually exclusive with `attachAppName` and `launchBundleId`.
- `deviceId` (string): UDID of a physical device. Mutually exclusive with `simulatorId`.
- `durationSec` (integer): Recording duration in seconds (default 90, max 600).
- `launchBundleId` (string): Launch app by bundle id and start recording at launch. Mutually exclusive with `attachAppName` and `attachPid`.
- `output` (string, required): Absolute path where the resulting `.trace` bundle should be written. Must end in `.trace`.
- `simulatorId` (string): UDID of a simulator. Mutually exclusive with `deviceId`. Use `listTraceDevices` to find UDIDs.
- `template` (string): xctrace template name (e.g. "Time Profiler", "Animation Hitches", "Allocations"). Default "Time Profiler".

### `captureMemgraph` (~168 tokens)

Capture a .memgraph from a running process

[mg.memory] Wrapper around `leaks --outputGraph`. Resolves `appName` to a PID via `pgrep -x` (or accepts `pid` directly), then writes a `.memgraph` snapshot. **Limitation**: only works for processes running on the local Mac (Mac apps + iOS simulator). Does NOT work for physical iOS devices, use Xcode's Memory Graph button there.

Input parameters:

- `appName` (string): App name (resolves to PID via `pgrep -x`). Mutually exclusive with `pid`.
- `output` (string, required): Absolute path where the `.memgraph` should be written. Must end in `.memgraph`.
- `pid` (integer): PID of the running process. Mutually exclusive with `appName`.

### `bootAndLaunchForLeakInvestigation` (~440 tokens)

Build, boot, install, and launch an iOS app for leak investigation

[mg.build] Single-call orchestration that runs `xcodebuild build` (optional), boots the iOS Simulator, installs the .app, and launches it with `MallocStackLogging=1` propagated via `SIMCTL_CHILD_*`. Required because `leaks --outputGraph` regressed on macOS 26.x and only works when the target was launched with malloc-stack-logging in its environment. Returns the host PID + simulator UDID + bundle id ready to chain into `captureMemgraph`. Auto-discovers BUILT_PRODUCTS_DIR, WRAPPER_NAME, EXECUTABLE_NAME, and PRODUCT_BUNDLE_IDENTIFIER from `xcodebuild -showBuildSettings -json`. Required: `scheme` and exactly one of `workspace` or `project`.

Input parameters:

- `buildBeforeLaunch` (boolean): Run `xcodebuild build` before installing. Set false when you've already built and want to skip straight to install/launch.
- `bundleId` (string): Override the bundle identifier. By default it is discovered from `xcodebuild -showBuildSettings`.
- `configuration` (string): xcodebuild configuration. Default "Debug".
- `derivedDataPath` (string): Custom -derivedDataPath. Useful to avoid collisions when multiple investigations run in parallel.
- `envVars` (object): Extra env vars to apply to the launched app (propagated via SIMCTL_CHILD_*). Default already includes MallocStackLogging=1.
- `launchArgs` (array): Extra arguments passed to the app on launch.
- `project` (string): Absolute path to a .xcodeproj. Mutually exclusive with `workspace`.
- `scheme` (string, required): Xcode scheme that builds the iOS application bundle.
- `simulator` (object): Pick a simulator by `udid`, by `name` (with optional `os`), or omit to use whichever simulator is currently booted.
- `warmupSeconds` (number): How long to wait after launch before resolving the host PID. Default 3 seconds.
- `workspace` (string): Absolute path to a .xcworkspace. Mutually exclusive with `project`.

### `replayScenario` (~395 tokens)

Replay a UI scenario to amplify a suspected leak

[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 `axe` (https://github.com/cameroncooke/AXe) — when missing, returns a structured workaroundNotice with install instructions. Tap targets accept `label`, `elementId`, or explicit `coords`.

Input parameters:

- `actions` (array, required): Ordered list of UI actions: { type: 'tap', label|elementId|coords }, { type: 'swipe', from, to }, { type: 'wait', seconds }, or { type: 'type', text }.
- `finalUITreePath` (string): When provided, after the scenario completes the final UI tree is written here as JSON for the caller to verify the app ended in the expected state.
- `repeat` (integer): Run the entire actions sequence this many times. Default 1. Use 5-10 to amplify subtle leaks that accumulate per repetition.
- `screenshotDir` (string): v1.15+. DebugSwift-inspired. When provided, captures a simulator screenshot after each action into `<screenshotDir>/iteration-{N}_step-{M}.png`. Useful for 'what was on screen when the leak fired?' c…
- `settleBetweenActionsMs` (integer): Pause between consecutive actions in milliseconds. Default 500. Increase for animation-heavy flows.
- `simulatorUDID` (string, required): UDID of the booted simulator. Use listTraceDevices to find one.

### `captureScenarioState` (~305 tokens)

Capture a labeled before/after snapshot for verify-fix

[mg.scenario] Composite snapshot: writes a `.memgraph`, a `.png` screenshot, and a `.ui.json` accessibility tree into `outputDir`, all prefixed by `label` (e.g. `before` / `after`). Designed to bracket a fix or a replayScenario call so you can chain into diffMemgraphs and validate that a cycle actually closed. Sub-captures are best-effort: if leaks fails (macOS 26.x minimal-corpse), the screenshot + UI tree still complete and the captureMemgraph workaroundNotice is surfaced for follow-up. Required: `simulatorUDID`, `outputDir`, and exactly one of `pid` / `appName`.

Input parameters:

- `appName` (string): App executable name as visible in pgrep. Mutually exclusive with `pid`.
- `include` (array): Which artifacts to capture. Default captures all three.
- `label` (string): Filename prefix for the captured artifacts. Use "before" / "after" for verify-fix flows.
- `outputDir` (string, required): Absolute directory where the snapshot files are written. Created if it does not exist.
- `pid` (integer): PID of the host-side app process. Mutually exclusive with `appName`. Pass the value returned by bootAndLaunchForLeakInvestigation.
- `simulatorUDID` (string, required): UDID of the booted simulator hosting the target app. Used for screenshot + UI tree captures.

### `analyzeAnimationHitches` (~375 tokens)

Analyze animation hitches from a .trace bundle

[mg.trace] Parse the `animation-hitches` schema from a `.trace` recorded with the Animation Hitches Instruments template. Returns hitch totals, by-type counts, longest hitches, and how many crossed the user-perceptible 100ms threshold.

Input parameters:

- `minDurationMs` (number): Filter out hitches shorter than this duration in milliseconds. Apple categorizes hitches >100ms as user-perceptible, pass 100 to focus on those.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `timeRangeMs` (object): Optional time-window filter. Only hitches whose `startNs` falls within `[startMs, endMs]` (milliseconds since recording start) are included. Use this to answer 'what hitches happened during this 5-se…
- `topN` (integer): Return the top N longest hitches in the response (default 10).
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with the Animation Hitches template (`xcrun xctrace record --template 'Animation Hitches' --attach <app|pid>`).

### `analyzeAllocations` (~309 tokens)

Analyze allocations from a .trace bundle

[mg.trace] Parse the `allocations` schema from a `.trace` recorded with the Allocations Instruments template. Returns per-category aggregates (cumulative bytes, allocation count, lifecycle = transient/persistent/mixed), top allocators by size and by count, and a one-liner diagnosis identifying the dominant allocator.

Input parameters:

- `minBytes` (number): Filter out individual allocations smaller than this size in bytes (default 0). Use 1024 to focus on >1KB allocations.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N allocators by aggregated size (default 15).
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with the Allocations template (`xcrun xctrace record --template Allocations --attach <app|pid>`).

### `analyzeAppLaunch` (~255 tokens)

Analyze cold/warm launch breakdown

[mg.trace] Parse the `app-launch` schema from a `.trace` recorded with the App Launch Instruments template. Returns total launch time, launch type (cold/warm), per-phase breakdown (process-creation, dyld-init, ObjC-init, AppDelegate, first-frame), and the slowest phase.

Input parameters:

- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with the App Launch template (`xcrun xctrace record --template 'App Launch' --launch <bundleId>`).

### `analyzeNetworkActivity` (~338 tokens)

Analyze HTTP / connection activity from a Network trace

[mg.trace] Parse the `network-connections` schema from a `.trace` recorded with a Network template. Returns per-request URL/host, method, status code, response time, bytes in/out. Top-N rankings by duration (which calls blocked the user) and by bytes (which calls bloat the budget) plus per-host aggregates surfacing chatty SDKs. v1.14+.

Input parameters:

- `minBytes` (number): Filter out connections that transferred fewer than this many bytes (in + out combined). Useful for cutting tiny pings out of the by-bytes view.
- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N rows for each ranking dimension (by-duration + by-bytes). Default 10.
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with a Network template (`xcrun xctrace record --template 'Network Profile' --attach <app|pid>`).

### `analyzeMemoryFootprint` (~297 tokens)

Analyze process VM footprint (resident / dirty / virtual)

[mg.trace] Parse the `memory-footprint` schema from a `.trace` recorded with Allocations or System Trace template. Returns peak resident bytes (RAM in use), peak dirty bytes (the OOM-kill discriminator on iOS), peak VM regions, per-sample timeline. Distinct from analyzeAllocations (cumulative malloc bytes by category). Use when investigating 'why is my app getting jetsam-killed?'. v1.15+.

Input parameters:

- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N memory snapshots ranked by resident bytes (default 10).
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with an Allocations or System Trace template that includes the memory-footprint instrument.

### `analyzeEnergyImpact` (~288 tokens)

Analyze energy use / battery drain from an Energy Log trace

[mg.trace] Parse the `energy-impact` schema from a `.trace` recorded with an Energy Log template. Returns per-sample bucket classification (idle / passive / active / high), aggregate wakeup count, active-state ratio, top-N samples by energy cost. The 'why is my app draining battery?' investigation. Distinct from analyzeTimeProfile (CPU sampling); reads the OS power-management subsystem directly. v1.15+.

Input parameters:

- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N samples ranked by energy cost descending (default 10).
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with an Energy Log template that includes the energy-impact instrument.

### `analyzeLeakTimeline` (~285 tokens)

Analyze leaks as a time series (xctrace Leaks instrument)

[mg.trace] Parse the `leaks` schema from a `.trace` recorded with a Leaks template. Distinct from leaks(1) CLI (snapshot): this is a time series of leak events captured throughout the recording. Returns per-class first-seen-at timestamp, peak instance count, peak bytes, event count. Useful for answering 'when in the timeline did the leak appear?' which the snapshot CLI cannot. v1.15+.

Input parameters:

- `outputFormat` (string): Response format. Omitted or `json` (default, preserves v1.8 behavior) returns JSON.stringify of the result. `markdown` renders a human-readable view of the same data. `both` returns both content item…
- `topN` (integer): Return the top N leaked classes ranked by peak instance count (default 10).
- `tracePath` (string, required): Absolute path to a `.trace` bundle recorded with a Leaks template.

### `recordViaInstrumentsApp` (~323 tokens)

Record a .trace via Instruments.app GUI (macOS 26.x workaround)

[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: `xcrun xctrace record` wedges on this OS but Instruments.app GUI still produces valid traces. Returns instructions[] for the user-in-loop step, tracePath when found, plus a chained inspectTrace summary. Times out after `timeoutSec` (default 600s). v1.16+.

Input parameters:

- `preexistingTraces` (array): Absolute paths to `.trace` bundles already in `watchDir`. The watcher excludes these so it only matches NEW files. When omitted, the watcher snapshots the directory at start. Optional override for ca…
- `template` (string): The Instruments template the user should pick after the app launches. Surfaced in the response's instructions array. Default 'Time Profiler'. Common alternatives: 'Allocations', 'Animation Hitches',…
- `timeoutSec` (integer): Maximum seconds to wait for the user to save a `.trace` before returning a timeout. Default 600 (10 minutes). Capped at 3600 (1 hour).
- `watchDir` (string): Directory to watch for the saved `.trace` bundle. When omitted, defaults to $MEMORYDETECTIVE_TRACE_ROOT (typically `~/Library/Application Support/memorydetective/traces`). The directory is created if…

### `analyzeMetricKitPayload` (~437 tokens)

Analyze a .mxdiagnostic payload from MetricKit (production diagnostics)

[mg.production] Parse Apple MetricKit `.mxdiagnostic` payloads from real-device TestFlight / App Store builds. Aggregates crashes (clustered by exception type / binary / top frame), hang hotspots (sorted by duration, with localized-string handling for `hangDuration`), CPU exceptions, and disk-write exceptions. Inputs: payloadPath (single file), payloadDir (aggregate across files), or payloadJson (raw). Each output entry includes the raw binaryUUID + offset for downstream dSYM symbolication. Returns 3 most-actionable sections + cross-tool chain hints (e.g. `objc_release` top frame -> findCycles, sqlite top frame -> analyzeHangs with main-thread-violation classifier). No symbolication in v1; that's a separate tool. Simulator does NOT generate MetricKit payloads (Apple-side limitation) — frame this as post-mortem analysis. New in v1.18.

Input parameters:

- `groupBy` (string): Clustering key for `crashCluster[]`. `exception-type` groups by exceptionType + signal (catches mass-crash on the same OS-level fault). `binary` groups by the top frame's binary name (catches crashes…
- `payloadDir` (string): Absolute path to a directory containing one or more `.mxdiagnostic` files. The tool walks the dir non-recursively and aggregates findings across all payloads.
- `payloadJson` (string): Raw `.mxdiagnostic` JSON string. For in-memory callers and tests; if both `payloadPath` and `payloadJson` are provided, `payloadJson` wins.
- `payloadPath` (string): Absolute path to a single `.mxdiagnostic` file (the JSON Apple's MetricKit writes to the app's MetricKit directory on real-device builds).
- `topN` (integer): Cap on `crashCluster[]` / `hangHotspots[]` / `cpuExceptions[]` / `diskWriteExceptions[]` length. Default 10.

### `renderCycleGraph` (~218 tokens)

Render a retain cycle as Mermaid or DOT graph

[mg.render] Read a `.memgraph`, pick a ROOT CYCLE by index, and emit the chain as a Mermaid graph definition (default — embeddable in markdown / GitHub) or a Graphviz DOT file. App-level classes are highlighted; CYCLE BACK terminators are styled distinctly. Use `cycleIndex` to render cycles other than the first.

Input parameters:

- `cycleIndex` (integer): Zero-based index of the ROOT CYCLE to render (default 0 = the first cycle, usually the largest).
- `format` (string): Output format: `mermaid` (GitHub-renderable, embeddable in markdown) or `dot` (Graphviz format).
- `maxDepth` (integer): Truncate the rendered graph beyond this chain depth (default 8).
- `path` (string, required): Absolute path to a `.memgraph` file.
- `truncateClassName` (integer): Truncate long generic SwiftUI class names to this many characters (default 60). The full name still appears in node IDs.

### `logShow` (~251 tokens)

Query macOS unified logging (one-shot)

[mg.log] Wrap `log show --style compact --last <window>` with optional NSPredicate filter, process and subsystem sugar. Returns parsed entries (timestamp, type, process, pid, subsystem, category, message) bounded by `maxEntries`. Use this to look back at app logs without leaving chat.

Input parameters:

- `last` (string): Time window to look back from now (e.g. "30s", "5m", "1h", "2d"). Default 5m.
- `level` (string): Minimum log level. `default` = default+error+fault. `info` adds info-level. `debug` adds info+debug.
- `maxEntries` (integer): Cap on parsed entries returned (default 500). Output is truncated to the first N matching.
- `predicate` (string): NSPredicate-style filter passed to `log show --predicate`. Examples: `process == "DemoApp"`, `subsystem == "com.example.app"`, `messageType == error`.
- `process` (string): Filter to a single process name. Sugar over `--predicate process == "<name>"`.
- `subsystem` (string): Filter to a single subsystem identifier.

### `logStream` (~127 tokens)

Stream macOS unified logging for a bounded window

[mg.log] Wrap `log stream --style compact` for a bounded duration (≤60 s — MCP requests should not block longer). Returns parsed entries collected during the window. Useful for capturing a specific user flow without setting up a full Console.app session.

Input parameters:

- `durationSec` (integer): How long to listen for log entries (max 60 seconds — MCP requests should not block longer). Default 10.
- `level` (string)
- `maxEntries` (integer)
- `predicate` (string)
- `process` (string)
- `subsystem` (string)

### `detectLeaksInXCUITest` (~374 tokens)

Run an XCUITest with leak detection (CI-runnable)

[mg.ci] Build the workspace for testing, launch the test cycle, capture a baseline `.memgraph` once the app appears, run the test to completion, capture an after `.memgraph`, and diff. Returns `passed: false` when new ROOT CYCLE blocks appear that aren't in the `allowlistPatterns` list. Designed for CI gating: non-zero exit code on failure.

Input parameters:

- `allowlistPatterns` (array): Substrings of class names that are allowed to leak. Examples: pre-existing SwiftUI internals you can't fix, third-party SDK leaks. Cycles whose root class contains any of these substrings won't fail…
- `appName` (string, required): App process name as it appears in `pgrep -x` (e.g. "DemoApp").
- `destination` (string): xcodebuild destination string. Default targets the most common iOS Simulator profile.
- `outputDir` (string): Directory where the baseline + after `.memgraph` snapshots are written.
- `outputHtmlPath` (string): Absolute path to write a self-contained HTML report (inline CSS, no external assets). When set, the response also gains an `htmlReportPath` field pointing at the same file. Designed for CI artifact u…
- `scheme` (string, required): Xcode scheme that builds and runs the XCUITest target.
- `skipBuild` (boolean): Skip the build-for-testing step (faster on CI when the build is already cached).
- `testIdentifier` (string, required): XCUITest identifier in `<TestTarget>/<TestClass>/<testMethod>` form. Passed to `-only-testing` so we run exactly one test cycle.
- `workspace` (string, required): Path to the .xcworkspace or .xcodeproj for the project.

### `detectLeaksInXCTest` (~614 tokens)

Run an XCTest unit-test bundle with leak detection (CI-runnable)

[mg.ci] Sibling to `detectLeaksInXCUITest`, targeting XCTest unit-test schemes. Build for testing, launch the test bundle with an optional `-only-testing:<TestTarget>/<TestClass>[/<testMethod>]` filter, poll for the runner process (`xctest` by default, configurable via `processName` for app-hosted test bundles), capture a baseline `.memgraph` once the runner appears, run the test to completion, capture an after `.memgraph`, and diff. Returns `passed: false` when new ROOT CYCLE blocks appear that are not in the `allowlistPatterns` list. Per-test granularity: call once per test method with different `testCaseFilter` values; aggregation is the caller's responsibility, keeping the response tied to a single, well-defined before/after pair. If the runner exits before the after-capture window (common for fast unit tests with no host), the response carries an explicit `failureReason` pointing at the `tearDown` workaround. Designed for CI gating: non-zero exit code on failure.

Input parameters:

- `allowlistPatterns` (array): Substrings of class names that are allowed to leak. Cycles whose root class contains any of these substrings will not fail the run.
- `destination` (string): xcodebuild destination string. Default targets the most common iOS Simulator profile.
- `outputDir` (string): Directory where the baseline + after `.memgraph` snapshots are written.
- `outputHtmlPath` (string): Absolute path to write a self-contained HTML report (inline CSS, no external assets). When set, the response also gains an `htmlReportPath` field pointing at the same file. Designed for CI artifact u…
- `processName` (string): Process name to attach `leaks` against. `xctest` is the default unit-test runner on the simulator. If your tests are hosted in an app, pass the host app's process name instead (the same value `pgrep…
- `project` (string): Path to the `.xcodeproj`. Mutually exclusive with `workspace`.
- `runnerStartTimeoutMs` (integer): How long to wait for the test runner process to appear under `pgrep -x <processName>` before giving up. Default 5 minutes.
- `scheme` (string, required): Xcode scheme that builds and runs the XCTest unit-test target.
- `skipBuild` (boolean): Skip the `build-for-testing` step (faster on CI when the build is cached).
- `testCaseFilter` (string): Optional `-only-testing` filter in `<TestTarget>/<TestClass>` or `<TestTarget>/<TestClass>/<testMethod>` form. Omit to run every test in the scheme (slower; produces one before/after pair for the ent…
- `workspace` (string): Path to the `.xcworkspace`. Mutually exclusive with `project`.

### `reachableFromCycle` (~266 tokens)

Count instances reachable from a specific cycle root

[mg.memory] Cycle-scoped reachability + class counting. Answers questions like "how many `NSURLSessionConfiguration` instances are reachable from the cycle rooted at `DetailViewModel`?" — distinguishing the actual culprit (the cycle root) from its retained dependencies. Pick a cycle by zero-based `cycleIndex` or by `rootClassName` substring. Returns per-class counts ranked by occurrence, plus the total reachable node count.

Input parameters:

- `className` (string): Optional filter — only count nodes whose className contains this substring. When omitted, returns the full per-class breakdown.
- `cycleIndex` (integer): Zero-based index of the ROOT CYCLE to scope to. Mutually exclusive with `rootClassName`. When neither is given, defaults to cycle index 0.
- `path` (string, required): Absolute path to a `.memgraph` file.
- `rootClassName` (string): Substring of the root cycle's class name (e.g. "DetailViewModel"). Picks the first ROOT CYCLE whose root matches. Mutually exclusive with `cycleIndex`.
- `topN` (integer): Cap on per-class entries returned (default 20).
- `verbosity` (string): Class-name verbosity for the response. See analyzeMemgraph for the same flag.

### `swiftGetSymbolDefinition` (~259 tokens)

Locate a Swift symbol's source declaration

[mg.code] Find the file:line where a Swift symbol (class, struct, enum, protocol, func, var, etc.) is declared. Pre-scans `candidatePaths` (or `hint.filePath`) with a fast regex first, then asks SourceKit-LSP for jump-to-definition. Returns the position even when LSP can't follow through. Use after `findRetainers` / `classifyCycle` surface a class name from a memgraph cycle to land in the actual source file.

Input parameters:

- `candidatePaths` (array): If provided, search these files for the symbol declaration before asking SourceKit-LSP. Speeds up location when the agent already has a guess (e.g. from `findSymbolReferences` or `swift_search_patter…
- `hint` (object): Optional hint to speed up the search. `filePath` skips the project scan; `module` is reserved for future multi-module work.
- `projectRoot` (string): Override the project root. Default discovers the nearest Package.swift / .xcodeproj / .xcworkspace from the cwd.
- `symbolName` (string, required): Name of the Swift symbol to locate (class, struct, enum, protocol, func, var, etc.).

### `swiftFindSymbolReferences` (~222 tokens)

Find every reference to a Swift symbol

[mg.code] Locates the symbol's declaration in `filePath`, then asks SourceKit-LSP for `textDocument/references`. Returns every callsite + capture across the project, with a snippet of each line. **Requires an IndexStoreDB** at `<projectRoot>/.build/index/store` for cross-file references — build it with `swift build -Xswiftc -index-store-path -Xswiftc <projectRoot>/.build/index/store`. The result includes a `needsIndex: true` hint when the index is missing.

Input parameters:

- `filePath` (string, required): Path to a Swift file where the symbol is declared. The LSP query needs a position; we locate it in this file via a regex pre-scan.
- `includeDeclaration` (boolean): Include the declaration site itself in the result set.
- `projectRoot` (string): Override the project root. Default discovers the nearest Package.swift / .xcodeproj / .xcworkspace.
- `symbolName` (string, required): Name of the Swift symbol to find references for.

### `swiftGetSymbolsOverview` (~140 tokens)

List top-level symbols in a Swift file

[mg.code] Cheap orientation: returns the top-level symbols (classes, structs, enums, protocols, free functions) declared in a Swift file via SourceKit-LSP's `documentSymbol`. Set `topLevelOnly: false` for nested children too. Useful right after `swiftGetSymbolDefinition` lands you in a new file.

Input parameters:

- `filePath` (string, required): Absolute path to a Swift source file.
- `projectRoot` (string)
- `topLevelOnly` (boolean): Return only top-level symbols (classes, structs, enums, protocols, free functions). When false, returns nested children too. Default true keeps responses small.

### `swiftGetHoverInfo` (~128 tokens)

Get type info / docs at a Swift source position

[mg.code] SourceKit-LSP `textDocument/hover` at a (line, character) position. Returns the markdown / plaintext hover content plus a best-effort extracted declaration fragment. Use to disambiguate `self` captures: a class self in a closure can leak; a struct self can't.

Input parameters:

- `character` (integer, required): Zero-based UTF-16 character offset within the line.
- `filePath` (string, required): Absolute path to a Swift source file.
- `line` (integer, required): Zero-based line number (LSP convention).
- `projectRoot` (string)

### `swiftSearchPattern` (~171 tokens)

Regex-search a Swift file (no LSP)

[mg.code] Pure regex search over a file's contents — no SourceKit-LSP, no IndexStoreDB. Catches what LSP misses: closure capture lists (`[weak self]`, `[unowned self]`), `Task { ... self ... }` blocks, and any other pattern the agent constructs from a leak chain. Returns matches with line/character positions and a trimmed snippet.

Input parameters:

- `filePath` (string, required): Absolute path to a Swift source file.
- `flags` (string): Additional RegExp flags ("i", "m", "s", "im", etc.).
- `maxMatches` (integer): Cap on matches returned (default 50).
- `pattern` (string, required): Regex pattern (JavaScript flavour). The `g` flag is implied — every match is returned.

### `getInvestigationPlaybook` (~139 tokens)

Get the canonical tool sequence for a known investigation kind

[meta] Returns a versioned, declarative pipeline for a known investigation flow (`memgraph-leak`, `perf-hangs`, `ui-jank`, `app-launch-slow`, `verify-fix`). Each step has a tool name, purpose, and argsTemplate. Use this once at the start of an investigation so any LLM agent can follow the right sequence without rediscovering it from individual tool descriptions.

Input parameters:

- `kind` (string, required): Which investigation flow to return. `memgraph-leak` is the most common — diagnose a SwiftUI/Combine retain cycle from a `.memgraph` and locate it in source.

### `verifyFix` (~476 tokens)

Verify a fix actually closed the targeted retain cycle

[mg.memory] Cycle-semantic diff. Classifies both `before` and `after` `.memgraph` snapshots and emits a per-pattern PASS/PARTIAL/FAIL verdict plus bytes freed and instances released. Use as a CI gate: if `expectedPatternId` is provided, `expectedPatternVerdict` tells you in one field whether the fix landed.

Pipeline: this is the natural followup to `classifyCycle` after you've shipped a fix. Capture a fresh `.memgraph`, point this at the before/after pair.

Input parameters:

- `after` (string, required): Absolute path to the post-fix `.memgraph`.
- `before` (string, required): Absolute path to the baseline `.memgraph` (pre-fix).
- `disableDefaultWhitelist` (boolean): v1.14+. When true, the curated DEFAULT_EXPECTED_ALIVE_CLASSES list is NOT applied. Only the user-supplied expectedAliveClasses (if any) is used. Useful for strict regression mode in tests where every…
- `expectedAliveClasses` (array): v1.14+. Class names that legitimately stay alive across the before/after snapshots. Singletons, framework registrars, persistent caches. When a class in this list appears in regressionClasses[], it i…
- `expectedPatternId` (string): If provided, the verdict is gated on whether this specific patternId disappeared from `after`. Defaults to checking every classified pattern.
- `verbosity` (string)

### `compareTracesByPattern` (~347 tokens)

Compare before/after .trace bundles for a perf regression target

[mg.trace][mg.ci] Trace-side counterpart to `verifyFix`. Compares two `.trace` bundles for a specific perf category (`hangs`, `animation-hitches`, or `app-launch`) and emits a PASS/PARTIAL/FAIL verdict plus before/after stats and deltas. Apply thresholds: hangs PASS when longest is below `hangsMaxLongestMs` (default 0); hitches PASS when longest is below `hitchesMaxLongestMs` (default 100ms — Apple's user-perceptible threshold); app-launch PASS when total is below `appLaunchMaxTotalMs` (default 1000ms).

Pipeline: capture before/after `.trace` (via `recordTimeProfile` or Xcode), then point this at the pair. The natural followup to a hangs/jank/launch fix PR.

Input parameters:

- `after` (string, required): Absolute path to the post-fix `.trace`.
- `before` (string, required): Absolute path to the baseline `.trace` (pre-fix).
- `category` (string, required): Which perf category to verify. `hangs` parses the `potential-hangs` schema, `animation-hitches` parses `animation-hitches`, `app-launch` parses the launch breakdown.
- `hangsMinDurationMs` (number): For `category: hangs` — only count hangs longer than this. Default 250ms (Apple's user-perceptible threshold for hangs).
- `hitchesMinDurationMs` (number): For `category: animation-hitches` — only count hitches longer than this. Default 100ms (Apple's user-perceptible threshold).
- `thresholds` (object)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective#diagnostics

## Score history

- 2026-08-03: 59
- 2026-08-02: 59
- 2026-08-01: 23
- 2026-07-31: 18
- 2026-07-30: 43
- 2026-07-28: 43
- 2026-07-27: 24

## Links

- npm package: https://www.npmjs.com/package/memorydetective
- Socket report: https://socket.dev/npm/package/memorydetective
- Repository: https://github.com/carloshpdoc/memorydetective
- Changelog RSS feed: https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective/changelog.json
- HTML version of this page: https://verifymcp.io/servers/carloshpdoc-memorydetective/memorydetective
