MCP Tools Reference
Loomem exposes 14 memory_* tools via the Model Context Protocol. These tools are what Claude (or any MCP client) uses to interact with memory. The MCP server identifies itself as loomem-memory.
Runtime sync: The condensed version sent to MCP clients lives in
loomem-server/mcp_instructions.md(embedded at compile time). Edit that file to change what clients see.
Scope model
Data lives in streams. Different tools operate at different scopes:
| Scope | Tools | What it means |
|---|---|---|
| Per-stream (isolated) | memory_store, memory_search, memory_ingest, memory_context, memory_profile, memory_dream, memory_reflect, memory_associate |
Only sees/writes data in the active stream |
| Global (engine-wide) | memory_status, memory_namespaces |
Returns system-level info |
| Per-stream (isolated graph) | memory_graph |
Knowledge graph is per-stream isolated |
| By chunk ID | memory_history, memory_delete, memory_feedback |
Operates on a specific chunk |
Key concepts:
- Stream — the data isolation boundary. The built-in default stream is __user_default__.
- Namespace — a human-readable label mapped to a stream ID (e.g., personal → 100). Configured in config.toml, listed by memory_namespaces.
Storing memories
memory_store
Store a single, confirmed fact.
Use for: explicit user statements, confirmed decisions, biographical facts.
Don't use for: raw conversation text — use memory_ingest instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
content |
string | yes | The fact to store |
source |
string | no | Provenance (e.g., "user-stated") |
subject |
string | no | Entity name (person, project) |
metadata |
object | no | Custom JSON metadata |
Example:
memory_store(
content: "Prefers Cursor over VSCode for AI features",
subject: "Alice",
source: "user-stated"
)
Behavior:
- Preferences automatically get importance: 2.0
- Entity extraction runs (dictionary + LLM queue)
- Contradiction detection checks against existing memories
- Embedding generated asynchronously
memory_ingest
Extract structured knowledge from a conversation via LLM. Preferred method for storing multi-fact content.
| Parameter | Type | Required | Description |
|---|---|---|---|
content |
string | yes | Conversation transcript |
conversation_date |
string | no | ISO date (e.g., "2026-04-02") |
Example:
memory_ingest(
content: "User: I switched from VSCode to Cursor last week. Also, the dashboard deadline is April 15th.",
conversation_date: "2026-04-02"
)
What happens:
1. LLM extracts individual facts with type, subject, date, confidence
2. Each fact checked for duplicates (cosine similarity > 0.92 = skip)
3. Contradiction detection runs (updates supersede older facts)
4. Facts stored with full extraction_meta
Typical output (illustrative — exact extraction depends on LLM judgment):
- PreferenceOrDecision: "User prefers Cursor over VSCode" (subject: user, confidence: 0.95)
- ProjectState: "Dashboard deadline is 2026-04-15" (subject: dashboard, confidence: 0.90)
The number of extracted facts, their phrasing, and confidence scores vary by input. Treat examples as representative, not contractual.
Searching memories
memory_search
Hybrid search across all memory tiers.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | yes | Search query |
top_k |
int | no | Max results (default: 10) |
time_filter |
string | no | "today", "this_week", "this_month" |
Example:
memory_search(query: "What IDE does the user prefer?")
Behavior:
- Runs BM25 + vector + graph search in parallel
- Applies time decay (recent memories score higher)
- Deduplicates near-identical results
- Marks superseded facts with [UPDATED]
- For aggregation queries ("how many..."), boosts top_k to 30
memory_context
Load relevant background at the start of a task. Token-budgeted — won't overwhelm the context window.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | no | Topic focus (e.g., "dashboard project") |
budget_tokens |
int | no | Max tokens (default: 4000) |
sections |
string[] | no | Which sections: profile, relevant, recent |
Example:
memory_context(query: "Loomem project", budget_tokens: 2000)
Section allocation:
- profile (20%) — who the user is, stable facts
- relevant (50%) — memories matching the query
- recent (30%) — last 7 days of activity
When to call: Once at conversation start, when the topic requires background knowledge.
memory_profile
Get the user's synthesized profile.
| Parameter | Type | Required | Description |
|---|---|---|---|
format |
string | no | "markdown" or "json" |
Returns:
- stable_facts — permanent truths (max 30)
- recent_context — last 7 days (max 15)
- summary — 2-3 sentence overview
Profile is LLM-generated and cached for 1 hour.
memory_associate
Surface serendipitous associations — memories that are surprisingly relevant but not obvious — using graph walks, temporal co-occurrence, and semantic adjacency.
Use for: unexpected connections and creative links across topics (e.g., "what past projects relate to this new idea?"). Use memory_search for direct fact retrieval.
Returns: a numbered list of associations with mechanism and score. If results are empty, clustering may not have run yet — call memory_dream first.
Memory maintenance
memory_dream
Trigger memory consolidation. Like sleep for the brain — merges, deduplicates, and organizes memories.
No parameters.
What happens: 1. Groups memories by subject 2. Merges related observations into concise summaries 3. Resolves contradictions (newer facts win) 4. Creates L1 compressed chunks from L0 raw events 5. Respects cost cap ($0.10/run by default)
Returns:
{
"chunks_processed": 50,
"groups_found": 12,
"facts_merged": 8,
"contradictions_resolved": 2,
"cost_usd": 0.04,
"duration_ms": 3200
}
When to call: - After a long, productive session - When the user asks to "clean up" or "consolidate" memory - Automatically triggered after 30 minutes of inactivity
memory_reflect
Analyze memory quality and get improvement suggestions.
| Parameter | Type | Required | Description |
|---|---|---|---|
max_chunks |
int | no | How many chunks to analyze |
Returns:
{
"quality_score": 78,
"breakdown": {
"by_level": { "L0": 45, "L1": 62 },
"with_extraction_meta": "87%",
"with_subject": "72%"
},
"suggestions": [
"28 chunks lack subject metadata — run memory_dream",
"5 potential contradictions detected"
]
}
Quality score formula: has_meta*0.4 + has_subject*0.3 + structured*0.3
When to call: Periodically (once per week), or when memory quality seems poor.
memory_graph
Explore entity connections in the knowledge graph. Per-stream isolated — each user sees only their own entities and connections.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Entity name to explore |
Example:
memory_graph(entity: "Cursor")
Returns: entity details (name, type, aliases), connections to other entities, linked chunk count. Only entities and edges within the active stream are visible.
Useful for understanding "who works on what", "what technologies are connected", etc.
memory_history
Trace how a fact evolved over time (version chain).
| Parameter | Type | Required | Description |
|---|---|---|---|
chunk_id |
string | yes | Chunk to trace |
limit |
int | no | Max versions to return |
Example:
memory_history(chunk_id: "abc-123")
Returns: version chain showing how the fact changed:
v1 (2026-03-15): "User uses VSCode" ← superseded
v2 (2026-04-01): "User uses Cursor" ← current
When to call: when the user asks "what did I use before X?" or when investigating contradictory information.
memory_delete
Delete a specific memory by ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
chunk_id |
string | yes | Memory to delete |
Important: Never delete without user confirmation.
memory_feedback
Rate the usefulness of a memory chunk after a task, providing a reinforcement signal to the ranking system.
| Parameter | Type | Required | Description |
|---|---|---|---|
chunk_id |
string | yes | Chunk to rate (from the id returned by memory_store / memory_ingest) |
usefulness |
int | yes | 0 (not useful) – 4 (crucial) |
harmful |
bool | no | Set only when the chunk contained incorrect or misleading information |
Only rate chunks where the usefulness is clear; this is not a general write tool.
Informational
memory_status
Engine health and statistics. Use to verify the engine is running, check capacity, or diagnose issues when other tools seem unresponsive.
No parameters.
When to call: - Tools return unexpected errors or empty results - User asks about memory health or capacity - Before a complex operation (bulk ingest, dream) to verify readiness
Returns:
{
"status": "ok",
"uptime_secs": 86400,
"rocksdb_keys": 311,
"tantivy_docs": 115,
"embeddings_count": 112,
"vector": true,
"tantivy": true,
"scheduler": true
}
Key indicators:
- vector: false means semantic search is degraded (BM25 only)
- scheduler: false means background workers (consolidation, decay, dream) are not running
- Large gap between rocksdb_keys and embeddings_count suggests embedding backfill needed
memory_namespaces
List available memory spaces.
No parameters.
Returns:
{
"namespaces": {
"personal": "100",
"work": "110"
}
}
Best practices
Do
- Use
memory_ingestfor conversations (notmemory_store) - Call
memory_contextat conversation start for relevant tasks - Run
memory_dreamafter productive sessions - Check
memory_reflectperiodically - Use
memory_searchbefore answering from training data
Don't
- Don't store raw conversation text via
memory_store - Don't call
memory_searchfor every response — only when recall matters - Don't store temporary status, small talk, or questions without answers
- Don't store passwords, API keys, or other secrets
- Don't delete without user confirmation