Skip to content

MCP Tools ​

Version 0.14 contract ​

The default store is Git-friendly JSON under the nearest project root's .remind/memory/; embeddings and indexes are disposable ignored caches. Use --store file:///absolute/path for another directory. Explicit SQL URLs continue to select SQL backends. See Storage and migration.

Reads return full opaque IDs and revision tokens. Existing-record writes require the inspected revision: --expected-revision for individual CLI edits, --revisions '{"full-id":"revision"}' for CLI apply, expected_revision/expected_revisions in MCP and Python, and If-Match on individual REST edits. Stale edits fail instead of overwriting newer memory. snapshot deleted supplies revisions for restore or bulk purge; bulk purge takes an expected_revisions map.

Recall is read-only by default. Explicit label filters constrain candidates, graph traversal, facts, and rendered context. Labels are generic tags; separate stores provide isolation. Structured recall includes text, concepts, episodes, warnings, and optional explanation. Source freshness warnings annotate changed/missing files without changing the remembered claim.

New workflow tools include remember_batch, generation-aware poll_events, and doctor. CLI equivalents are remember-batch, events --since <generation.cursor>, and doctor. REST exposes POST /api/v1/workflow/{operation} for remember, remember-batch, recall, apply, snapshot, events, and doctor. Use idempotency keys for capture/apply retries. Portable export includes facts, conflicts, evidence, labels, events, and retry receipts; --mode backup also includes derived vectors.

Tools available when connecting to Remind via MCP.

remember ​

Store an experience as an episode.

remember(content="User prefers TypeScript", episode_type="preference")
remember(content="Use Redis for caching", episode_type="decision", entities="tool:redis,subject:caching")
remember(content="Cache TTL is 300s", episode_type="fact", entities="tool:redis", labels="topic=infra", asserted_by="alice", source_ref="https://github.com/org/repo/pull/42")
ParameterTypeRequiredDescription
contentstringYesThe experience to store
metadatastringNoOptional JSON string with additional metadata
episode_typestringNoobservation (default), decision, question, preference, meta, outcome, fact
entitiesstringNoComma-separated entity tags (type:name)
labelsstringNoComma-separated key=value labels (e.g. "topic=architecture" or "topic=architecture,team=infra")
source_typestringNoOrigin of this memory (e.g. "agent", "slack", "github", "manual")
asserted_bystringNoWho asserted this information (provenance)
source_refstringNoLink back to the original artifact (URL/permalink)

Fact episodes ​

When episode_type="fact", the episode is:

  1. Stored and embedded
  2. Clustered by entity overlap with existing facts
  3. Checked for collisions with active facts in the cluster

The response includes:

  • fact_id — the new fact's ID
  • cluster_id — the fact cluster it was assigned to
  • cluster_created — whether a new cluster was created
  • collisions — existing active facts with entity overlap

Handle collisions via apply with supersede or conflict ops.

remember_batch ​

Atomically capture multiple separate assertions. Keep facts, decisions with rationale, and observed outcomes as distinct items even when they came from one message.

text
remember_batch(items=[
  {"content": "Retries are limited to 4", "episode_type": "fact"},
  {"content": "Use backoff to avoid overload", "episode_type": "decision"},
  {"content": "Backoff reduced errors", "episode_type": "outcome"}
], idempotency_key="capture-123")
ParameterTypeRequiredDescription
itemsarrayYesCapture objects using remember fields; results preserve input order
idempotency_keystringNoStable key for safely retrying the same batch

Returns {"results": [...]} with the full remember result for every item.

recall ​

Retrieve relevant memories.

recall(query="authentication issues")
recall(query="auth", entity="file:src/auth.ts")
recall(entity="file:src/auth.ts")
recall(query="database design", labels="topic=architecture")
recall(query="cache configuration", as_of="2024-06-01")
recall(query="auth", max_chars=2000)
recall(query="auth", min_score=0.3, timeout_ms=500)
ParameterTypeRequiredDescription
querystringNoSearch query (required for semantic search)
kintegerNoNumber of concepts to return (default: 3)
contextstringNoAdditional context to improve retrieval
entitystringNoScope to entity (can be used alone)
episode_kintegerNoEpisodes via direct vector search (default: 5, 0 to disable)
labelsstringNoComma-separated key=value label filter (e.g. "topic=architecture"). Strictly filters candidates, graph traversal, and rendered context.
as_ofstringNoISO date/datetime for time-travel (facts valid at that point)
max_charsintegerNoCap the formatted output length; drops lowest-ranked concepts/episodes whole (never mid-item) until it fits
min_scorefloatNoDrop concepts/episodes below this activation score even if k/episode_k budget remains
timeout_msintegerNoSoft deadline; returns best-so-far instead of raising if exceeded

At least one of query or entity must be provided.

If the output shows an OPEN CONFLICTS warning, triage with list_conflicts / resolve_conflict / dismiss_conflict.

apply ​

Batch write for transactional memory curation. All-or-nothing; returns per-op results.

Compact format (preferred) ​

One op per line, shlex tokenization, key=value args, trailing quoted string = content/note:

remember as=f1 t=fact e=tool:redis by=alice "Cache TTL is 600 seconds"
supersede old=fact:a91c2 new=$f1
remember as=o1 t=outcome e=subject:auth "SameSite=Strict broke OAuth; Lax required"
concept as=c1 from=ep:11,ep:12 title="Retry with backoff" "Transient failures resolve with backoff"
resolve id=conflict:7 winner=fact:b3d01 "confirmed by bob"
processed ids=ep:11,ep:12
ParameterTypeRequiredDescription
changesetstringYesOps in compact or JSON format
dry_runbooleanNoValidate without executing

Operations ​

OpArgumentsDescription
rememberas, t, e, by, ref, contentStore episode (batched)
supersedeold, newReplace old fact with new
conflictfact_a, fact_b, severity, descriptionOpen a conflict
resolveid, winner, noteResolve conflict (winner supersedes loser)
dismissid, noteDismiss conflict (both stay active)
conceptas, title, from, type, relations, summaryCreate concept from episodes
updateid, field=value...Update episode/concept fields
linkfrom, to, typeAdd concept relation
labelid, key, valueAdd a key=value label to episode/concept
unlabelid, key, valueRemove a key=value label from episode/concept
entity_relationsource, target, relation, strength, contextAdd a typed relation between entities
evidenceconcept, episode, type, strength, noteLink an episode to a concept as supporting/contradicting/exemplifying/qualifying evidence
unlinkconcept, episodeRemove an evidence link
reshapeid, type, reasonChange a concept's type (e.g. pattern → hypothesis)
mergefrom, into, reasonMerge overlapping concepts (sources soft-deleted with lineage)
splitid, into, reasonSplit a concept into multiple new concepts
deleteidSoft delete
restoreidRestore deleted item
processedidsMark episodes as reviewed

Local refs: Use as=name to declare, $name to reference within the changeset.

JSON format ​

json
[
  {"op": "remember", "as": "f1", "t": "fact", "content": "Cache TTL is 600s",
   "e": ["tool:redis"], "by": "alice"},
  {"op": "supersede", "old": "fact:a91c2", "new": "$f1"},
  {"op": "resolve", "id": "conflict:7", "winner": "fact:b3d01", "note": "confirmed"}
]

snapshot ​

Batch read returning current memory state as JSON. Combine scopes in a single call.

snapshot(scopes="pending")                    # Unprocessed episodes with entities
snapshot(scopes="conflicts")                  # Open conflicts with fact context
snapshot(scopes="pending,conflicts")          # Both at once
snapshot(scopes="entity:tool:redis")          # All data for an entity
snapshot(scopes="labels")                     # All distinct labels with counts
snapshot(scopes="label:topic=architecture")   # All data for a label
snapshot(scopes="concept:abc123")             # Concept detail with facts/history
snapshot(scopes="recent:20")                  # 20 most recent episodes
snapshot(scopes="stats")                      # Memory statistics
snapshot(scopes="query:cache config")         # Semantic search (concepts only)
ParameterTypeRequiredDescription
scopesstringYesSpace or comma separated scope specifiers

Scopes:

  • pending — Episodes not yet processed, with their entities
  • conflicts — Open conflicts with both facts and provenance
  • entity:<id> — Entity detail with episodes and fact clusters
  • labels — All distinct key=value labels in use, with counts
  • label:<key>=<value> — All episodes and concepts carrying a label
  • concept:<id> — Concept detail including superseded fact history
  • recent:<n> — N most recent episodes
  • stats — Memory statistics
  • query:<text> — Semantic search for concepts
  • events[:<cursor>] — Change-feed poll. Generation-qualified cursors use the durable contract; numeric values retain legacy projection-local behavior. Prefer poll_events.
  • bootstrap[:<n>] — Query-free stable context: top-n actionable concepts by confidence and instance count, plus open conflict count and stats (default 10). Needs no embedding call and is deterministic for a given memory state — cheap enough to call every session, or to place in a system prompt via an injection layer.

poll_events ​

Poll durable changes using a generation-qualified cursor:

text
poll_events()                                  # Initial poll
poll_events(cursor="<generation.cursor>")      # Resume from next_cursor
poll_events(cursor="<generation.cursor>", limit=50)
ParameterTypeRequiredDescription
cursorstringNonext_cursor from the previous response
limitintegerNoMaximum number of events (default: 200)

Returns {count, events, next_cursor, reset_required}. Persist next_cursor. If reset_required is true, discard projection-local state and restart from the returned cursor; this can occur after checkout, merge, or a cache rebuild.

events (legacy numeric polling) ​

events remains available for compatibility with consumers that use a numeric sequence from one projection. New integrations should use poll_events.

events()                                       # All events from the start
events(since_seq=42)                           # Only events after seq 42
events(since_seq=42, kind="conflict_opened")   # Filter to one kind
ParameterTypeRequiredDescription
since_seqintegerNoOnly return events with seq greater than this (default: 0)
limitintegerNoMaximum number of events to return (default: 200)
kindstringNoFilter to a single event kind

Returns {since_seq, count, events, next_since_seq}. Numeric sequences are local to one disposable projection and are not stable across rebuilds. Every successful remember and every successful apply op appends one row, atomically with the write it describes. kind is one of remembered, superseded, conflict_opened, conflict_resolved, conflict_dismissed, concept_created, updated, labeled, unlabeled, deleted, restored, processed. Each event has seq, ts, kind, subject_type, subject_id, and an optional payload.

list_conflicts ​

List detected memory conflicts (contradictions) awaiting triage.

list_conflicts()
list_conflicts(status="all")
list_conflicts(status="open", kind="fact")
ParameterTypeRequiredDescription
statusstringNoopen (default), resolved, dismissed, or all
kindstringNoFilter by fact or concept

resolve_conflict ​

Resolve a conflict by declaring which fact is correct. The losing fact is structurally superseded (kept as history, hidden from recall).

resolve_conflict(conflict_id="conflict:7", winning_fact_id="fact:b3d01", note="confirmed in prod config")
ParameterTypeRequiredDescription
conflict_idstringYesThe conflict to resolve (from list_conflicts)
winning_fact_idstringNoThe correct fact's ID (required for fact conflicts)
notestringNoWhy this resolution is correct
resolved_bystringNoWho decided

dismiss_conflict ​

Dismiss a conflict: both claims are valid (e.g. different contexts). Both facts stay active.

dismiss_conflict(conflict_id="conflict:7", note="staging vs prod, both true")
ParameterTypeRequiredDescription
conflict_idstringYesThe conflict to dismiss (from list_conflicts)
notestringNoWhy this isn't a real contradiction
resolved_bystringNoWho decided

inspect ​

Inspect concepts or episodes in memory (list all, view one, or filter episodes by date range).

inspect()
inspect(concept_id="abc123")
inspect(show_episodes=True, start_date="2024-01-01", end_date="2024-01-31")
ParameterTypeRequiredDescription
concept_idstringNoID of a specific concept to inspect
show_episodesbooleanNoShow episodes instead of concepts
limitintegerNoMaximum number of items to show (default: 10)
start_datestringNoISO date/datetime, inclusive start (episodes only)
end_datestringNoISO date/datetime, inclusive end (episodes only)

stats ​

Memory statistics: concept/episode counts, consolidation status, relation type distribution.

stats()

doctor ​

Diagnose canonical record integrity, embedding compatibility, and source freshness.

text
doctor()
doctor(repair_indexes=True)
ParameterTypeRequiredDescription
repair_indexesbooleanNoRebuild disposable indexes before diagnosing (default: false)

episode_types ​

List episode types configured for this project/environment (built-in and custom).

episode_types()

entities ​

List entities (files, functions, people, etc.) mentioned in episodes.

entities()
entities(entity_type="tool", limit=20)
ParameterTypeRequiredDescription
entity_typestringNoFilter by type: file, function, class, module, concept, person, project, tool, other
limitintegerNoMaximum number of entities to show (default: 50)

inspect_entity ​

Inspect an entity and its relationships to other entities.

inspect_entity(entity_id="file:src/auth.ts")
ParameterTypeRequiredDescription
entity_idstringYesEntity ID to inspect (e.g. "file:src/auth.ts", "person:alice")
show_relationsbooleanNoWhether to include relationships (default: True)

update_episode ​

Update an existing episode — correct mistakes, reclassify, or relabel. Only provided fields are updated.

update_episode(episode_id="ep:11", content="Corrected information")
update_episode(episode_id="ep:11", labels="topic=architecture,team=infra")
update_episode(episode_id="ep:11", labels="")  # clear all labels
ParameterTypeRequiredDescription
episode_idstringYesID of the episode to update
contentstringNoNew content text (resets the episode for re-consolidation)
episode_typestringNoNew type
entitiesstringNoNew comma-separated entity IDs
plan_idstringNoPlan episode ID to link this task to
spec_idsstringNoComma-separated spec episode IDs to link this task to
depends_onstringNoComma-separated task IDs this task depends on
prioritystringNoPriority level: p0, p1, or p2
labelsstringNoComma-separated key=value labels; replaces all existing labels; empty string clears them

delete_episode / restore_episode ​

Soft delete or restore an episode.

delete_episode(episode_id="ep:11")
restore_episode(episode_id="ep:11")

update_concept ​

Update an existing concept — refine or correct generalized knowledge. Only provided fields are updated.

update_concept(concept_id="c-123", summary="Refined summary")
update_concept(concept_id="c-123", labels="topic=architecture")
ParameterTypeRequiredDescription
concept_idstringYesID of the concept to update
titlestringNoNew short title
summarystringNoNew summary text (clears the embedding; regenerates on next recall)
confidencefloatNoNew confidence score (0.0-1.0)
tagsstringNoNew comma-separated tags
relationsstringNoJSON array of relations, e.g. [{"type":"implies","target_id":"abc","strength":0.7}]
labelsstringNoComma-separated key=value labels; replaces all existing labels; empty string clears them

delete_concept / restore_concept ​

Soft delete or restore a concept.

delete_concept(concept_id="c-123")
restore_concept(concept_id="c-123")

list_deleted ​

List soft-deleted episodes and concepts.

list_deleted()
list_deleted(item_type="episodes", limit=50)
ParameterTypeRequiredDescription
item_typestringNo"episodes", "concepts", or omit for both
limitintegerNoMaximum number of items to show per type (default: 20)

Released under the Apache 2.0 License.