nMEMORY
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {} |
| resources | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| memory_aliasA | Teach recall a synonym: pass term + alias to record the pair (both are normalized: lowercased + diacritic-folded). DIRECTION IS ONE-WAY, as taught: querying |
| memory_bootstrapA | One deterministic COLD-START pack for a fresh agent — the PULL half of the recall loop (memory_retrieve is per-task recall; this answers "what must I know before I act?"). ONE call composes the digest/retrieve/list read primitives into five sections IN THIS FIXED ORDER: (1) constraints — active kind=constraint capsules in scope (tier active, NOT expired, NOT superseded; tombstoned already excluded) — what you CANNOT do, surfaced FIRST, before what to do; (2) ready — the blocks-dag ready set fenced to scope (the SAME projection memory_digest exposes, fail-closed on a live blocks-cycle: |
| memory_classifyA | Classify content into {kind: fact|procedure|decision|task|epic|brainstorm|doc|constraint|capability|failure_pattern, scope: project|global|session, authority_class, instruction_taint}. origin (extracted-candidate|owner-stated|tool-observation|external-import|session-note; default extracted-candidate) drives authority and default scope; external-import is BORN tainted. Pass kind to carry a memory_extract candidate's kind forward (never re-derived); omit it to derive from the content via the extract cue tables — closed ENGLISH + PORTUGUESE keyword lists (typed error when underivable — nothing is guessed; other languages: pass kind explicitly; the same extract ENTITY GATE applies, so a declarative/copular sentence derives a fact ONLY with an entity anchor — an acronym/number/path/dotted/backtick token — and "o sistema é resiliente" is underivable while "a API é lenta" derives fact). The schema-minimal call {content} is therefore wire-valid only when the content carries a derivable cue — the minimal ALWAYS-valid call is {content, kind}. taint_hint=true is monotone (never cleared by a clean local scan). With capsule_id (alias id — memory_get/memory_forget spell it id; capsule_id is canonical, both at once is a duplicate-field error) the label is PERSISTED as that capsule's sidecar record (upsert; audited) and readable back on memory_get's classification field; without it the call is advisory only. A persist onto a live capsule also answers content_matches_capsule — false means the label was derived from OTHER bytes than the capsule holds (the persist still executes, but the drift is named on the response and in the audit detail, never bound silently). Optional epistemic sidecar (u-r2, REQUIRES capsule_id — advisory-only calls carrying these are rejected with the teaching error, never silently dropped): evidence_state (closed set observed | inferred | unverified — how the claim relates to observation), proof_hint (the command that re-proves the claim), stale_if (the condition under which the claim expires). Persisted PER FIELD — an omitted field never clears a stored one — and read back on memory_get's epistemics and on retrieve envelopes. proof_hint/stale_if are ADVISORY STRINGS stored and surfaced verbatim, NEVER executed or evaluated by any code path. |
| memory_consolidateA | Run the deterministic consolidation planner over the live store and return the full plan: exact_dupes (same-source_hash rows — a store-invariant breach report; keep = lowest seq), merge_proposals (near-duplicate clusters by significant-token containment; tainted never clusters with untainted), tier_moves (protective demotions only: quarantine on live taint evidence for externally-imported records, archive for superseded records that expired or aged >180d with zero recalls; NEVER a promotion to active), and alias_proposals (u-r5 miss-ledger: deterministic vocabulary hints mined from the recall-miss ledger — each recorded miss term is paired with every existing indexed-vocabulary word sharing a >=4-char folded prefix (prefix-on-fold ONLY: no fuzzy, no edit-distance, no scoring, no embedder), {term, candidate, miss_count} ordered miss_count desc then term asc then candidate asc, capped at the top 20; a term that already carries a taught alias is skipped, and a term with no candidate still surfaces as {term, candidate:null, miss_count}. The loop: memory_retrieve records a miss -> this proposes -> you teach memory_alias -> the SAME query grounds). Default is a pure DRY-RUN: nothing is written. apply_tiers:true executes ONLY the tier_moves (set_tier per move, each audited); merge proposals, dupe repairs, AND alias_proposals are NEVER executed or auto-taught by this tool — teaching an alias stays a caller act through memory_alias; the caller is always the deciding actor. Applied tiers are observable on every read surface: memory_get carries tier, memory_list rows mark (and filter by) non-active tiers, memory_export renders tier markers, and memory_retrieve counts archived/quarantined exclusions under their OWN reasons (tier fences dominate the superseded fence). Everything returned is ADVISORY_NOT_AUTHORITY. |
| memory_digestA | Compact store projection sized for session-start injection: total capsule count, counts by project, a handoff section LEADING the headline lists — discovered by TWO markers: bracket handoffs (rows whose provenance source is "memory_session_finish", i.e. captured by memory_session_finish's handoff; ONE row per project, a superseded row stays visible flagged) and thread handoffs (rows whose content opens with the exact convention ACTIVE(): — closing paren required — captured via plain memory_ingest; ONE row per project+thread so concurrent threads stay visible, and a superseded thread row is RETIRED: supersede a thread's newest handoff to close the thread out of the lead — a guarantee that assumes each thread capture supersedes its prior (an older LIVE unchained row of the same thread resurfaces instead)); newest-first, house headline rows, capped at N; ABSENT when the scope holds none — additive, a reader that never hands off sees the digest unchanged, the newest N headlines with ids, and the N most-recalled headlines — each carrying the recall_count and last_recalled_at (RFC3339) that ordered it, sorted recall_count desc, then LAST-RECALL recency (not creation recency), then append order; capsules never returned by memory_retrieve do not appear. EVERY capped list declares its own completeness: handoff_total, newest_total and most_recalled_total are the EXACT pre-cap counts of their lists (the dag's ready/ready_total idiom), fenced exactly like the lists they sit beside and omitted at zero, so a truncated list is never mistaken for a complete one — list length < total means N cut it, raise headlines to see the rest. total and by_project's |
| memory_exportA | Render the whole store as one deterministic markdown INDEX view and return it as a string under the response's |
| memory_extractA | Mine a free-text blob (param |
| memory_forgetA | Forget a capsule's content IRREVERSIBLY (reason MANDATORY). The capsule's embedding sidecar row is destroyed WITH it (both modes — a vector is derived from the destroyed bytes and the id stops being enumerable on memory_vector's list). mode "purged" = hard forget, nothing retained; "redacted" = the provenance {source, anchor} is deliberately RETAINED on the marker for audit — both destroy the content bytes (secure_delete) and empty the recall index row. What remains is the tombstone marker: id, mode, at, reason, a KEYED HMAC-SHA-256 content fingerprint (key from NMEMORY_HMAC_KEY or a 0600 key file beside the DB, created on first use), the id's relation edges, and — redacted only — the retained provenance. Afterwards: memory_get answers the marker envelope (memory_list omits tombstoned ids); retrieve counts it under excluded {tombstoned} ONLY when a query term IS the capsule id itself (e.g. terms:["cap-3"]); the content index row is EMPTIED, so searching the forgotten content abstains — zero matches, no tombstone echo; re-ingesting the identical content is rejected (forget is sticky); the id drops out of the digest dag (forget is a sanctioned dag repair); forgetting the id AGAIN is a resource-state error (-32002, data {kind: "tombstoned_capsule", id}) — the same family as an unknown id, never a fake invalid-params. Audited with the reason. |
| memory_getA | Fetch ONE full capsule by exact store id (cap-) — the expansion step of layered recall after retrieve/digest/list returned a headline. Response is wrapped as ADVISORY_NOT_AUTHORITY DATA and carries the complete capsule: content, provenance, confidence, freshness, scope, authority_class, instruction_taint — plus relations (every edge touching this id: kind/from/to/at, plus origin:"import" on a machine-written stale-import supersedes edge — absent means caller-recorded 'manual', the only kind the machine never reverses — the "what blocks/supersedes/witnesses this?" read surface), classification (the persisted memory_classify sidecar label, when one exists), event_time (the caller-declared fact-time sidecar when one exists: event_from, event_to, declared_at; GET-only — never emitted by list, digest, export, or retrieve envelopes; set only on fresh capture via memory_ingest), epistemics (u-r2: the persisted epistemic sidecar when one exists — evidence_state from the closed observed|inferred|unverified set, proof_hint, stale_if, at; the two hints are ADVISORY STRINGS surfaced verbatim, never executed or evaluated; set them at capture via memory_ingest or later via memory_classify with capsule_id), tier (the effective lifecycle tier active/archived/quarantined — always present, so apply_tiers results are auditable per capsule), expired (true when valid_to has passed at read time — the recall-fence state made visible instead of leaving freshness arithmetic to the reader; absent when still current), and taint_findings (the u6e scan re-run over the stored content — WHICH hijack rule fires, one "rule: term, term" line each; absent when clean), and last_mutation ({actor, at, event} — the most recent audit-ledger row whose subject is this id, so "who mutated this?" reads off the API instead of the SQLite ledger; actor is the clientInfo.name recorded at mutation time; absent when the id was never a mutation subject). A forgotten id answers with its tombstone marker envelope (outcome "tombstoned": mode, at, reason, content_hmac, relations, last_mutation — for a tombstone that is the forget itself, so "who forgot this?" reads off the API — and, for mode redacted only, the deliberately retained provenance {source, anchor}; never content). Unknown id -> resource-not-found (-32002) with data {kind: "unknown_capsule", id}. |
| memory_importA | Import memories from ONE closed native source: "user-claude-md" (/.claude3/CLAUDE.md, else .claude2, else .claude), "project-claude-md" (/CLAUDE.md), "project-agents-md" (/AGENTS.md), or "memory-dir" (every .md DIRECTLY inside dir — non-recursive, symlinks skipped; dir required for this source only). base overrides the resolved base directory. Split rule (derivable, not vague): fenced code is opaque (never split inside, headings within a fence do not count). If the file has ATX headings at column 0, the split level is the SMALLEST heading level that occurs at least TWICE (a lone "# Title" over "##" sections splits per "##"), else the smallest level present — so a file with ONE top-level heading is ONE candidate carrying the whole body; candidates are the preamble before the first split-level heading (if non-blank) then one per split-level section (deeper headings ride along inside). With NO headings, candidates are blank-line-separated paragraph blocks. Each candidate is trimmed of surrounding blank lines; whitespace-only candidates are dropped. Each candidate is taint-scanned and ingested with authority_class=externally-imported and instruction_taint=true (imports are BORN tainted — no waiver) under provenance anchor : — the path is ROOT-RELATIVE when the source sits under the repo anchor root (so anchor_live can resolve it), absolute otherwise (anchor_live stays "unknown" — the fence resolves only root-relative paths, never over-claiming liveness). Batch outcome shape of memory_ingest (captured/deduplicated/rejected per candidate; idempotent re-import dedupes). Outcome split (q103): PARAM faults stay hard -32602 (a memory-dir source without a dir; a dir passed to another source; a memory-dir path that is not a directory); SOURCE-STATE results are SOFT typed rows sharing one family — outcome "imported" (candidates ingested), "absent" (no file at any probed path, with the tried list), or "rejected" (a whitelisted leaf blocked by a security fence — today a leaf that is itself a symlink, never followed — carrying the fence's VERBATIM reason plus the leaf path; the security signal stays fully visible, never a protocol error). STALE-IMPORT SUPERSESSION (u-r8): re-import repairs what it derived — a capsule derived from a source block that CHANGED is auto-superseded by the fresh capture (lineage-bound by per-block content hash, NEVER similarity; equal-count guard defers unbalanced edits to the caller), and content that REAPPEARED (a revert) is revived by climbing the chain of the mechanism's OWN origin='import' supersedes edges to a head anchored in this source. THE FENCE: a hand-ingested capsule is never auto-superseded or auto-revived, a caller-recorded (manual) edge is never machine-reversed — ANY manual edge on the chain makes the machine defer with zero mutation. Every machine edge and revive is audited and marked origin='import' (visible on memory_get). |
| memory_ingestA | Capture memories with MANDATORY provenance (source + anchor). One item object, or a batch as {"items":[...]} — never both forms in one payload. A shape-broken batch item becomes its OWN rejected row plus the full contract; the good siblings still capture — schema-bad and semantically-bad items behave identically per-item, and every batch rejection row speaks ONE grammar: itemsN: ingest rejected: (the index always leads, the field path appears when a wrong-typed field is named, exactly one prefix; single-form SEMANTIC rejections carry the same prefix without the items[N] locator — a single-form SHAPE-broken payload (unknown/missing field, wrong type, invalid kind) is a DESERIALIZE-stage fault and surfaces IN-BAND as an isError result with plain serde text (rmcp 2.2.0 routes shape faults there, not to a protocol error; q88)). Idempotent by content hash: re-ingesting identical content collapses onto the existing capsule (per-item status "deduplicated"; fresh appends report "captured"; both statuses share one row shape). Smart defaults fill confidence (0.6), valid_from (now), project, authority_class (agent-inferred). When the server was booted without an explicit project (--project/NMEMORY_PROJECT absent), the default project derives at capture time from the connected client's clientInfo.name, sanitized to a slug (lowercase ASCII alphanumerics + '-', 32-char cap); pass project_id to pin. A server booted with an explicit project ignores clientInfo entirely. Externally-imported items are born instruction_taint=true. Every capture is taint-scanned: hijack-shaped content is flagged instruction_taint=true (advisory — it is stored flagged, never blocked) with per-rule taint_findings on the outcome. Optional fact-time per item: event_at (RFC3339 point) XOR event_from+event_to (inclusive RFC3339 range, to >= from) — stored as a sidecar (Capsule v1 untouched; a dedup collapse keeps the FIRST declaration), read back on memory_get.event_time, filtered by memory_retrieve's time_window; fact-time never feeds decay. Optional session_id links the capture to an open memory_session_start bracket. Optional kind (closed set fact|procedure|decision|task|epic|brainstorm|doc|constraint|capability|failure_pattern) is persisted as the capsule's classification sidecar right after capture (scope defaults to project; Capsule v1 bytes untouched) — so a task/epic becomes memory_list {kind} -listable in ONE trip instead of an ingest+classify pair; on a deduplicated row the kind still lands on the existing capsule — a DIFFERENT kind replaces the prior label (last-write-wins, the same audited upsert memory_classify performs; omitting kind never clears one; when the label actually flips, the dedup row says so with reclassified:{was,now} — a true no-op collapse omits it) — and an invalid kind rejects the item naming the closed set. Optional epistemic sidecar per item (u-r2, persisted beside the capsule the same via-ingest way; Capsule v1 bytes untouched): evidence_state — the closed set observed (directly seen) | inferred (proof supports it, not directly seen) | unverified (a hypothesis awaiting a check); an invalid state rejects the item naming the set — plus proof_hint (the command that re-proves the claim) and stale_if (the condition under which the claim expires); BOTH hints are ADVISORY STRINGS stored and surfaced verbatim, NEVER executed or evaluated by any code path; all three read back on memory_get's epistemics and on retrieve envelopes. A path:line anchor that resolves under the repo anchor root also has its anchored FILE's content hash recorded at capture (fail-closed fence: symlinks/absolute/out-of-root record nothing), so retrieve can answer anchor_drift — whether the anchored file's bytes changed since capture. Returns one outcome per item plus captured/deduped/rejected counts. dedup_hint is a near-duplicate advisory naming the NEAREST similar live capsule (max score; ties break to the earliest-appended id). The score is MUTUAL containment over the FULL vocabularies — every token counts, so a short differentiator ("wave A" vs "wave B", "v2" vs "v3") always lands the score below 1.0 — normalized by the LARGER set (a short content inside a long capsule scores low); eligibility needs 4+ significant (3+ char) tokens per side. The score tops out at 0.99: 1.0 is reserved for byte-identical content, which deduplicates and never hints, so 0.99 means the vocabularies coincide but the bytes differ — never treat a hint as proof of identity; the CALLER decides: replace it by re-ingesting with supersedes: "cap-" (the old capsule then stops grounding recall but stays reachable via memory_get/list; the outcome row confirms with superseded: "cap-", also when the new content deduplicated), or keep both. Captured rows may ALSO carry siblings: the top-3 highest-overlap ACTIVE capsules in the SAME project scope as the capture (same metric, same 0.5 threshold, same 0.99 cap as dedup_hint), each {id, score} — the write-time conflict surface, so near-siblings and contradictions surface NOW instead of sessions later in consolidate. Sibling candidacy applies recall's protective fences at write time: tombstoned, quarantined, falsified, archived, and superseded capsules never appear (you must not be steered to supersede into a dead or poisoned record), and neither does the capsule this very request supersedes. siblings is computed independently of dedup_hint — the hint scans globally, siblings are project-fenced — so the hint's target appears among the siblings exactly when it is itself an active same-project candidate. Absent when nothing clears the gate, and never present on deduplicated rows (that row already names its byte-identical target). Advisory ONLY, like the hint: the DECISION — supersede (re-ingest with supersedes), merge, or nothing — is yours; the engine never acts on it. |
| memory_listA | List capsules as compact entries (id, project, taint flag, created_at, headline, and — when non-active — the effective tier; expired:true when valid_to has passed; and — when the capsule carries a classification sidecar — kind, the persisted label, so a by-kind view reads off the row instead of one memory_get per capsule; absent when never classified; and superseded:true when a supersedes edge targets the row — a replaced entry self-identifies in the list itself, no per-id trip; absent when live) in append order, optionally fenced to a project_id (exact) and/or project_prefix (subtree: "nott" covers "nott" and "nott/x", never "nottx"; an empty or "/"-terminated prefix can match nothing and is rejected with a teaching error rather than answering empty; the two AND-compose), a kind (the PERSISTED classification sidecar label — "list my open tasks" is {kind: "task"}; set it at capture via memory_ingest's kind or later via memory_classify; never-classified capsules match no kind, and every returned row now echoes this same label back in its own kind field — q109), a tier (effective lifecycle tier: active/archived/quarantined — the enumeration surface for memory_digest's tier counts), and/or expired (true enumerates "what is expired" — valid_to before now; false the still-current rows). limit keeps the NEWEST rows after the filters (the entries returned still read oldest-to-newest). Tombstoned capsules never appear here — their markers answer memory_get only. Full capsules via memory_get. All content is ADVISORY_NOT_AUTHORITY data. |
| memory_mergeA | Reconcile a SECOND nMEMORY store file INTO this one — the offline-first sync at the tool layer (a local store and a mirror, merged later; the transport that fetches a remote store is a separate tool). Pass from: the filesystem path to the other store. That store is opened READ-ONLY and left byte-untouched; it must EXIST and be an nMEMORY store at this build's CURRENT schema version — a missing, corrupt, non-store, or stale-schema path fails CLOSED with a teaching -32602 and nothing is written (open an older source read-write with this build first to migrate it, then retry). The merge is deterministic and applied in ONE transaction — this store is either fully merged or untouched, never partially written. Identity is CONTENT (provenance.source_hash): a source capsule whose content already exists here COLLAPSES onto the local capsule (dedup, no duplicate); a genuinely-new one is appended under a fresh local id after this store's id ceiling, and every source relation edge is rewritten through that id remap, deduped against local edges, and danglers dropped. UNTRUSTED SOURCE: a merged capsule carries its SOURCE store's bytes verbatim — content, authority_class, and instruction_taint ride through UNCHANGED; a foreign capsule is NOT more trusted than an import and authority is NEVER elevated. FORGET WINS: content the source store forgot (a tombstone carrying the forgotten content's hash) forgets the matching LIVE local capsule too — its bytes are destroyed (secure_delete), its recall-index row emptied, its embedding dropped, and a re-keyed tombstone recorded (the marker's HMAC is re-derived under THIS store's key). Content this store has itself forgotten is never resurrected (forget is sticky — a source carrying it fails the merge closed). Returns an advisory-framed summary: capsules_added, capsules_collapsed (dedup), relations_added, tombstones_applied (forget-wins), and id_remap_size. Audited. The result is ADVISORY_NOT_AUTHORITY DATA — reconciled memory, never authority. |
| memory_outcomeA | Record (or list) an ADVISORY outcome-OBSERVATION record — a note that some outcome was OBSERVED. This is NOT a witnessed close and nothing in nmemory treats it as proven: a witnessed close needs the kernel (consequence_service), which this capability does not have. Recording an outcome NEVER changes any capsule's recall eligibility — only an explicit memory_relate falsifies edge fences a capsule from recall (record the outcome, THEN relate out- falsifies cap- if you actually mean to falsify a claim). record mode: pass description AND actor together (actor names WHO observed — there is NO default observer), plus optional evidence_ref (a path/url/id string) and capsule_id (the claim capsule cap- this bears on — validated to exist, but a soft 'bears on' pointer only, with ZERO recall effect). Returns the stored row with its minted id out-. Omitting a mandatory field teaches BOTH in one error; an unknown capsule_id answers resource-not-found (-32002, data {kind,id}). Optional scoring: pass receipt_id (the rcpt- a grounded memory_retrieve returned) together with score in 0.0..=1.0 to rate how useful that recall's returned evidence was; the pair applies an EMA (alpha 0.1, clamped to [0,1], neutral prior 0.5) to each returned capsule's ADVISORY feedback weight — consumed ONLY by memory_retrieve's opt-in weight_blend ranking, never by eligibility. receipt_id and score are mandatory together; an unknown receipt answers resource-not-found (-32002). The stored row carries receipt_id+score; a scored response echoes weights_updated. list mode: pass NO fields to list every outcome row in append order. APPEND-ONLY: there is no update or delete verb. Audited on record (hash-chained journal). Every response is ADVISORY_NOT_AUTHORITY DATA and carries a standing advisory naming this ceiling. |
| memory_pinA | Pin (or unpin) ONE capsule so decay never erodes it and the consolidation planner never archives it (S1). Pass id (cap-), pinned (true to pin, false to unpin), and a non-empty reason — pin is a WITNESSED, audited act. A pinned capsule ranks by its FULL confidence on every memory_retrieve and memory_bootstrap surface: decay is exempted at the ranking call site and the stored confidence is NEVER mutated; the archive arm of memory_consolidate skips it. Pin is NEVER eligibility — the recall fences (quarantine / falsified / archived / superseded / currency) run UNCHANGED, so a pinned+superseded (or quarantined or falsified) capsule stays EXCLUDED from recall: pin protects a live grounding capsule, it never resurrects a fenced one. Taint dominates pin: a pinned capsule that is instruction-tainted AND externally-imported still QUARANTINES under memory_consolidate (a pin can never launder taint). Unpin (pinned:false) resumes decay from valid_from. APPEND-ONLY: each call appends a pin/unpin event and state is the latest event; there is no separate delete. Audited (hash-chained journal). An unknown id answers resource-not-found (-32002, data {kind,id}); a tombstoned id, or an empty reason, is a teaching -32602. The pin surfaces as a |
| memory_preferenceA | Record (or list) ONE pairwise preference-evidence datum (u6i): preferred_id was chosen over rejected_id, in context, as observed by actor. PAIRWISE ONLY — no score, no ranking, no aggregation beyond the list count. This is EVIDENCE SUBSTRATE for a FUTURE owner-chosen mechanism; nothing in nmemory consumes it yet (it influences no recall and no ranking). record mode: pass preferred_id + rejected_id + context + actor together (all four mandatory). Both ids must name stored capsules — an unknown id answers resource-not-found (-32002, data {kind,id}); a self-pair (preferred_id == rejected_id) is rejected (a preference is two DISTINCT capsules). Returns the stored row with its minted id pref-. Omitting a mandatory field teaches ALL in one error. list mode: pass NO fields to list every preference row in append order. APPEND-ONLY: there is no update or delete verb. Audited on record (hash-chained journal). Every response is ADVISORY_NOT_AUTHORITY DATA and carries a standing advisory naming the rung. |
| memory_relateA | Record ONE directed, typed relation edge from --kind--> to. Closed kinds: supersedes (from replaces to), derived_from (from was materialized out of to), witnesses (from is evidence attesting to — the ATTESTED to, when a blocks-participant, becomes DONE in memory_digest's blocks-dag: proof-carrying CLOSURE that leaves ready/blocked and stops gating dependents yet STAYS recallable — distinct from supersede's REPLACEMENT and forget's DESTRUCTION), blocks (from blocks to — feeds memory_digest's blocks-dag ready/blocked/done projection; cycles are detected there, fail-closed with the concrete cycle — repair = supersede, forget, OR witness a member), falsifies (from contradicts capsule to — the target becomes recall-INELIGIBLE, its bytes untouched and still served by memory_get/list; it is NOT a dag input), proposes (from PROPOSES to replace to — b2 staged review; NAVIGATIONAL only: no dag/ready/done effect and no recall-exclusion effect, and never auto-converted to supersedes), part_of (from is a member of container to — pure membership; NEVER a dag input, so it is byte-inert to the blocks-dag; to MUST be a capsule persisted as kind 'epic' or 'task' — classify the container first), grounded_in (from — the child task/epic/plan node — hangs off parent to; the planning-plane anchor surfaced by memory_digest's mission section, NEVER a dag input). Endpoints: to is ALWAYS a stored capsule; from is a stored capsule too — EXCEPT falsifies, whose from may instead be a stored OUTCOME record id (out- from memory_outcome), i.e. an observed outcome falsifying a claim (capsule→capsule falsifies is also allowed). Edges are readable back on memory_get's relations list (and memory_export / the memory_digest relations count). Both endpoints must be stored (tombstoned still counts — edges are history); self-relations are rejected. Re-recording an edge is an idempotent no-op keeping the first timestamp, answered with already_recorded: true (a fresh write answers false). Recording a falsifies edge is the ONLY way to fence a capsule from recall this way — an outcome record alone never does. Every edge recorded here carries origin 'manual' — a caller decision the machine NEVER auto-reverses; only the stale-import mechanism's own origin='import' supersedes edges can be machine-reversed on re-import (memory_get shows origin on import edges; first write wins on replay). Audited. |
| memory_retrieveA | Recall stored memories. Pass caller-expanded terms (your own synonyms/aliases/rephrasings as separate terms; include inflected variants — matching is word-exact, no stemming: "token" does not find "tokens"). At least one term is required (schema minItems:1), and every term must carry at least one alphanumeric character — a punctuation-only or empty term is rejected with a teaching -32602. When the term lane runs, each term is ALSO expanded with its memory_alias-taught aliases (an alias hit grounds and is explained as alias: in matched_terms). Lane routing is the closed set auto|term|vector|fused: omitted/auto preserves historical selection (term without query_embedding, fused with it); term runs only FTS even when a vector is present; vector runs no FTS and requires query_embedding; fused runs both and requires query_embedding. When it runs, the term lane OR-matches terms via FTS5; WITHIN a term, words are AND-matched order/adjacency-insensitively ("tokio pin" finds "pin tokio at 1.38") and Latin diacritics fold ("configuracao" finds "configuração"). Limitation: unspaced scripts (CJK) index as whole runs between spaces/punctuation — a CJK word inside a run will not match; recall CJK content by a full delimited run, store it pre-segmented, OR teach a memory_alias mapping the CJK word to the full run (the alias then grounds the recall). Scope fences: project_id (exact), project_prefix (subtree: "nott" covers "nott" and "nott/x", never "nottx"), and optional session_id AND-compose before ranking. session_id is a character-exact store-local capsule label fence, not authentication or a globally unique bracket identity: accepted bytes are never trimmed, folded, normalized, shape-checked, or length-checked; only a whitespace-only value is rejected. It never consults the sessions table or expires, so finished, orphaned, and merge-imported labels remain recallable. Different stores may both label capsules "sess-1"; after memory_merge, filtering that label intentionally grounds every matching capsule. A non-matching label means no capsule with that label, never an unknown session. Optional time_window {from?, to?} (RFC3339, at least one bound) fences PRE-RANKING by declared fact-time, including BEFORE vector_k selects the vector lane's top eligible cosine matches: a capsule grounds only when its event range intersects the window; capsules without a declaration are excluded and counted as undated (excluded gains outside_time_window/undated). Ranking is lane-specific. Term-only ranking uses coverage descending, then bm25 ascending, then the advisory decay key (confidence × 2^(-age_days/90) from valid_from), freshness, usage late keys, and append order; envelopes carry decayed_weight SERIALIZED ROUNDED to 2 decimals (0.548992 rides the wire as 0.55; ordering uses the unrounded key), and stored confidence is never mutated. Forced-vector ranking uses one-lane RRF over cosine rank. Fused ranking uses two-lane RRF over the independent term and vector ranks. RRF ties use append order, and fusion_rank preserves the pre-weight-blend RRF position. Results are few, dense, token-budgeted (nonzero budget always returns the top result even if it alone overshoots — the floor of one; token_budget 0, like limit 0, returns none; trimmed_by_limit/trimmed_by_budget name the cut cause). Results ride under the |
| memory_session_finishA | Close an open session bracket (exactly once) with an optional summary — and an OPTIONAL handoff: the distilled close (what became true / what is open / the next physical action). A present handoff is captured as a NORMAL capsule through the audited ingest path BEFORE the bracket closes — provenance source "memory_session_finish", anchor = the session id, linked to the bracket; project-fence defaults, taint scan, and idempotent dedup all apply — and memory_digest then LEADS with the newest handoff per project (its handoff section), so the next cold session reads the close first. The response names the capsule (handoff_capsule; handoff_deduped: true when the content collapsed onto an existing capsule). A value-rejected handoff (e.g. empty content) fails the WHOLE call with -32602 naming the param — fail closed: nothing captured, the session stays open. A closed bracket accepts no further captures. Both state faults are typed resource-state errors, one family (-32002 + data {kind, id}): an unknown id → {kind: "unknown_session", id}; finishing an already-finished bracket → {kind: "finished_session", id} (never a discriminator-less invalid-params) — a handoff never leaks a capture past either. Audited. |
| memory_session_startA | Open a session bracket and return its deterministic store-minted id (sess-). Link captures to it via memory_ingest's session_id; close it with memory_session_finish. Audited. |
| memory_vectorA | Attach (or LIST) a CALLER-FED embedding — the u6a semantic sidecar. nmemory computes NO embedding (zero embedder dependency, zero network): YOU compute the vector with your own model and put it here; recall's semantic lane is DORMANT until you do. PUT: pass capsule_id (its |
| memory_visualA | Render the store as ONE deterministic Mermaid diagram (a generated view — nmemory writes no files; the caller pastes the string returned under the response's |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| nmemory_document | Readable generated-store document for memory_export |
| nmemory_visual | Interactive view for memory_visual Mermaid projections |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/menot-you/n-memory'
If you have feedback or need assistance with the MCP directory API, please join our Discord server