MCP Tools
Engram exposes 18 tools over the Model Context Protocol. Each tool is available to any MCP-connected AI client. Parameters follow the JSON Schema standard.
store_memoryStore a new memory. The content is embedded into a 384-dimensional vector and indexed for semantic search.
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | The text content to remember. |
| type | string | No | "episodic" | "semantic" | "procedural". Default: "episodic" |
| source | string | No | Identifier for the calling tool (e.g. "claude-code"). |
| tags | string[] | No | Tags for categorization. |
| importance | number | No | Importance score 0–1. Default varies by type (episodic: 0.5, semantic: 0.7, procedural: 0.6). |
| concept | string | No | For semantic memories: concept label for the knowledge graph. |
| sessionId | string | No | Session ID to group related episodic memories. |
| namespace | string | No | Override namespace for this memory. |
Example
// Store a semantic fact
{
"content": "The API server runs on Fastify with WAL-mode SQLite",
"type": "semantic",
"importance": 0.85,
"concept": "Tech stack — API"
}
// Response
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "semantic",
"content": "The API server runs on Fastify with WAL-mode SQLite",
"importance": 0.85,
"createdAt": "2025-03-21T10:00:00.000Z"
}recall_contextAssemble the most relevant context from all memories for a given query. Returns formatted context ready to use in AI prompts. This is the primary tool for giving AI models access to their memories.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | The text query to match against stored memories. |
| maxTokens | number | No | Maximum context tokens to return (100–8000). Default: 2000. |
| types | string[] | No | Filter by memory type(s). Default: all types. |
| sources | string[] | No | Filter by source systems (e.g. ["claude-code", "ollama"]). |
| crossNamespace | boolean | No | If true, recall from all namespaces. Default: false. |
| progressive | boolean | No | If true, return memories grouped by recall phase (vector, graph). Default: false. |
Example
// Recall context for a new conversation
{
"query": "Working on the Engram API server — what do I need to know?",
"maxTokens": 2000
}
// Response
{
"context": "[NEURAL MEMORY CONTEXT]\n[KNOWLEDGE]\n• The API server runs on Fastify...",
"memoriesUsed": 4,
"latencyMs": 18,
"memories": [
{
"id": "a1b2c3d4-...",
"type": "semantic",
"score": "0.940",
"source": "claude-code"
}
]
}
// Progressive mode — grouped by phase
{
"query": "API server setup",
"progressive": true
}
// Response
{
"context": "[NEURAL MEMORY CONTEXT]\n...",
"memoriesUsed": 6,
"latencyMs": 24,
"phases": {
"vector": { "count": 4, "memories": [/* high-confidence direct matches */] },
"graph": { "count": 2, "memories": [/* graph-expanded neighbors */] }
}
}search_memoryPure semantic search — returns memories ordered by vector similarity only, without recency or importance weighting. Useful for explicit knowledge lookup.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Search query. |
| topK | number | No | Number of results (1–50). Default: 10. |
| threshold | number | No | Minimum similarity 0–1. Default: 0.3. |
| types | string[] | No | Filter by memory type(s). |
| crossNamespace | boolean | No | If true, search across all namespaces. Default: false. |
Example
// Find facts about the database layer
{
"query": "SQLite WAL mode performance",
"types": ["semantic"]
}
// Response
{
"count": 1,
"results": [
{
"id": "a1b2c3d4-...",
"type": "semantic",
"content": "SQLite WAL mode enables 10k+ writes/sec",
"importance": 0.8,
"source": "claude-code",
"createdAt": "2025-03-21T..."
}
]
}add_knowledgeConvenience wrapper for store_memory that defaults to type=semantic. Designed for adding factual knowledge to the graph.
| Parameter | Type | Required | Description |
|---|---|---|---|
| concept | string | Yes | The concept or entity name (e.g. "TypeScript", "User"). |
| content | string | Yes | The fact or knowledge content. |
| tags | string[] | No | Categorization tags. |
| importance | number | No | Importance score 0–1. Default: 0.7. |
Example
// Add a knowledge node
{
"concept": "HNSW Vector Index",
"content": "HNSW vector index gives ~6ms search over indexed vectors",
"importance": 0.80
}
// Response
{
"id": "a1b2c3d4-...",
"concept": "HNSW Vector Index",
"message": "Knowledge stored"
}memory_statsReturns aggregate statistics about the memory store — counts by type, source, graph metrics.
No parameters required.
Example response
{
"total": 1247,
"byType": {
"episodic": 680,
"semantic": 412,
"procedural": 155
},
"bySource": {
"claude-code": 820,
"ollama": 310,
"openclaw": 117
},
"indexSize": 1247,
"graphNodes": 1247,
"graphEdges": 2843
}forgetArchive (soft-delete) memories from the brain. Memories are excluded from future recall but not permanently destroyed.
| Parameter | Type | Required | Description |
|---|---|---|---|
| ids | string[] | Yes | Array of memory IDs to archive. |
| reason | string | No | Reason for forgetting (logged only). |
search_memory first to find the IDs you want to forget.Example
// Archive specific memories
{
"ids": ["a1b2c3d4-...", "e5f6a7b8-..."],
"reason": "Outdated deployment instructions"
}
// Response
{
"archived": 2,
"reason": "Outdated deployment instructions",
"message": "Archived 2 memory(ies)"
}decay_sweepRun a memory decay sweep — evaluates all memories and archives stale ones based on the decay policy. Also triggers auto-consolidation of old episodic memories if enabled.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dryRun | boolean | No | If true, compute what would be archived without actually modifying anything. Default: false. |
Example
// Preview what would be archived (dry run)
{
"dryRun": true
}
// Response
{
"scannedCount": 101,
"archivedCount": 12,
"archivedIds": ["a1b2c3d4-...", "e5f6g7h8-...", "..."],
"decayedCount": 34,
"protectedCount": 8,
"consolidatedCount": 0,
"newSemanticIds": [],
"durationMs": 45,
"mode": "dry-run",
"message": "Dry run: would archive 12 memories, decay 34, consolidate 0"
}dryRun: true first to preview the impact before archiving memories.decay_policyView or update the memory decay policy configuration. Controls how aggressively memories are forgotten and when auto-consolidation runs.
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | string | Yes | "get" to view current policy, "update" to modify it. |
| halfLifeDays | number | No | Ebbinghaus half-life in days. Default: 7. |
| archiveThreshold | number | No | Retention score (0–1) below which memories are archived. Default: 0.05. |
| importanceDecayRate | number | No | Daily importance reduction rate. Default: 0.01. |
| importanceFloor | number | No | Minimum importance after decay. Default: 0.05. |
| consolidationEnabled | boolean | No | Enable or disable auto-consolidation. Default: true. |
Example
// Get current policy
{ "action": "get" }
// Update: slower decay, higher threshold
{
"action": "update",
"halfLifeDays": 14,
"archiveThreshold": 0.1
}
// Response
{
"policy": {
"halfLifeDays": 14,
"archiveThreshold": 0.1,
"decayIntervalMs": 3600000,
"batchSize": 200,
"importanceDecayRate": 0.01,
"importanceFloor": 0.05,
"consolidation": {
"enabled": true,
"minClusterSize": 3,
"similarityThreshold": 0.6,
"minEpisodicAgeMs": 86400000
},
"protectionRuleCount": 4
},
"message": "Policy updated"
}check_contradictionsCheck a memory for contradictions with existing memories, or list all unresolved contradictions. Detects negation, value changes, temporal overrides, and opposite sentiment.
| Parameter | Type | Required | Description |
|---|---|---|---|
| memoryId | string | No | Memory ID to check. If omitted, lists all unresolved contradictions. |
Example
// Check a specific memory
{ "memoryId": "a1b2c3d4-..." }
// Response
{
"hasContradictions": true,
"contradictions": [
{
"newMemoryId": "a1b2c3d4-...",
"existingMemoryId": "e5f6g7h8-...",
"similarity": 0.872,
"confidence": 0.637,
"signals": [
{ "type": "negation", "description": "Content contains negation...", "weight": 0.75 }
],
"suggestedStrategy": "keep_newest"
}
],
"candidatesChecked": 5,
"latencyMs": 18
}
// List all unresolved (no memoryId)
{}
// Response
{
"count": 2,
"contradictions": [
{
"confidence": 0.637,
"metadata": { "signals": ["negation"], "suggestedStrategy": "keep_both" },
"source": { "id": "...", "content": "The app uses MongoDB...", "type": "semantic" },
"target": { "id": "...", "content": "The app uses PostgreSQL...", "type": "semantic" }
}
]
}resolve_contradictionResolve a contradiction between two memories using a strategy. Removes the contradicts graph edge and optionally archives one of the memories.
| Parameter | Type | Required | Description |
|---|---|---|---|
| sourceId | string | Yes | ID of the first memory in the contradiction. |
| targetId | string | Yes | ID of the second memory in the contradiction. |
| strategy | string | Yes | "keep_newest" | "keep_oldest" | "keep_important" | "keep_both" | "manual" |
Example
// Resolve by keeping the newest memory
{
"sourceId": "a1b2c3d4-...",
"targetId": "e5f6g7h8-...",
"strategy": "keep_newest"
}
// Response
{
"resolved": true,
"strategy": "keep_newest",
"keptId": "a1b2c3d4-...",
"archivedId": "e5f6g7h8-...",
"message": "Contradiction resolved via keep_newest. Kept: a1b2c3d4-..., Archived: e5f6g7h8-..."
}check_contradictions first to review what will be archived before resolving. The keep_both strategy is the safest — it preserves both memories.embedding_statusGet the status of the embedding model — shows current model, dimension, and how many memories need re-embedding (stale or legacy).
No parameters required.
Example response
{
"currentModel": "Xenova/all-MiniLM-L6-v2",
"currentDimension": 384,
"totalEmbedded": 1247,
"currentModelCount": 1200,
"staleCount": 0,
"legacyCount": 47,
"needsReEmbed": true,
"message": "47 memories need re-embedding (0 stale, 47 legacy)"
}re_embedRe-embed memories with the current embedding model. Use after switching models to update stale vectors. Can be slow for large stores.
| Parameter | Type | Required | Description |
|---|---|---|---|
| onlyStale | boolean | No | If true, only re-embed stale/legacy memories. Default: true. |
| batchSize | number | No | Batch size for processing (1-100). Default: 32. |
Example
// Re-embed only stale memories
{ "onlyStale": true }
// Response
{
"total": 47,
"processed": 47,
"failed": 0,
"failedIds": [],
"durationMs": 2340,
"model": "Xenova/all-MiniLM-L6-v2",
"message": "Re-embedded 47 memories in 2340ms"
}embedding_status first to check how many memories need re-embedding before triggering a potentially long operation.index_statusGet the vector index status — how it was loaded (fast disk cache or full DB rebuild), entry count, and startup performance.
No parameters required.
Example response
{
"loadedFrom": "disk",
"entryCount": 1247,
"dimension": 384,
"indexPath": "/data/engram.db.index",
"indexFileExists": true,
"incrementalCount": 3,
"initDurationMs": 45,
"message": "Index loaded from disk cache (1247 entries, 3 added incrementally, 45ms)"
}list_tagsGet the tag cloud (all unique tags with counts), or get memories for a specific tag.
| Parameter | Type | Required | Description |
|---|---|---|---|
| tag | string | No | If provided, returns memories with this tag. If omitted, returns the tag cloud. |
| limit | number | No | Max memories to return when filtering by tag. Default: 50. |
Example
// Get tag cloud
{}
// Response: { "count": 8, "tags": [{ "tag": "typescript", "count": 42 }, ...] }
// Get memories by tag
{ "tag": "typescript", "limit": 5 }
// Response: { "tag": "typescript", "count": 5, "memories": [...] }tag_memoryAdd or remove a tag on a memory.
| Parameter | Type | Required | Description |
|---|---|---|---|
| memoryId | string | Yes | Memory ID to tag/untag. |
| tag | string | Yes | Tag to add or remove. |
| action | string | No | "add" (default) or "remove". |
Example
// Add a tag
{ "memoryId": "a1b2c3d4-...", "tag": "important" }
// Response: { "id": "a1b2c3d4-...", "tags": ["existing", "important"], "message": "Tag \"important\" added" }
// Remove a tag
{ "memoryId": "a1b2c3d4-...", "tag": "outdated", "action": "remove" }plugin_listList all registered Engram plugins with their hooks and metadata.
No parameters required.
Example response
{
"count": 1,
"plugins": [
{
"id": "my-org/logger",
"name": "Memory Logger",
"version": "1.0.0",
"hooks": ["onStore", "onRecall"],
"registeredAt": "2026-03-25T..."
}
],
"message": "1 plugin(s) registered"
}webhook_subscribeSubscribe a URL to receive HTTP POST callbacks when memory events occur. Supports HMAC-SHA256 signing.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | HTTP(S) URL to receive events. |
| events | string[] | Yes | Events: stored, forgotten, decayed, consolidated, contradiction. |
| secret | string | No | Shared secret for HMAC-SHA256 signature. |
| description | string | No | Human-readable description. |
Example
{
"url": "https://example.com/engram-hook",
"events": ["stored", "contradiction"],
"description": "Notify on new memories and conflicts"
}
// Response
{
"id": "a1b2c3d4-...",
"url": "https://example.com/engram-hook",
"events": ["stored", "contradiction"],
"active": true,
"message": "Webhook subscribed: a1b2c3d4-..."
}webhook_listList all webhook subscriptions with their status, event filters, and failure counts.
No parameters required.
Example response
{
"count": 2,
"webhooks": [
{
"id": "a1b2c3d4-...",
"url": "https://example.com/engram-hook",
"events": ["stored", "contradiction"],
"active": true,
"failCount": 0,
"description": "Notify on new memories"
}
]
}