Memory-MCP
Powers LLM-driven memory summarization, automated memory extraction through an AI judge, and serves as a fallback embedding provider when local options are unavailable.
Provides local embedding generation for semantic search using models like qwen3-embedding, with GPU acceleration support for privacy-focused vector operations.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Memory-MCPfind debugging solutions for Python async timeout errors"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Memory-MCP Server
Version: 3.8.0
Status: Production-Ready
License: MIT
A state-of-the-art persistent memory system for AI agents using hybrid search (vector embeddings + BM25 FTS), neural reranking, and optional LLM-driven automated memory extraction.
Table of Contents
Related MCP server: hive-memory
Overview
Memory-MCP is a production-grade persistent memory system for AI coding agents (Claude Code, Cursor, Windsurf, custom agents, etc.) that stores and retrieves valuable insights across sessions. It combines semantic vector search with keyword matching (BM25) for optimal retrieval accuracy.
What Problems Does This Solve?
Lost Knowledge: Valuable insights from debugging sessions, configurations, and patterns are forgotten between sessions
Context Switching: Hard to recall what worked in previous projects
Duplicate Effort: Solving the same problems repeatedly
Scattered Notes: Knowledge lives in different formats across different projects
How It Works
Save Memory → Embedding Generation → Duplicate Check → Store in LanceDB
↓
Recall Memory → Hybrid Search (Vector + BM25) → RRF Fusion → Neural Rerank → ResultsIntelligent Storage: Stores insights with 1024-dimensional semantic embeddings
Hybrid Retrieval: Searches using both semantic similarity AND keyword matching
Neural Reranking: CrossEncoder re-ranks results for maximum relevance
Optional Auto-Save: Hook analyzes agent actions and extracts memories automatically
Key Features
Feature | Description |
7 MCP Tools | Full CRUD operations + stats + health monitoring |
Hybrid Search | Vector (70%) + BM25 FTS (30%) with RRF fusion |
Neural Reranking | CrossEncoder (mxbai-reranker-base-v2, BEIR SOTA) |
Local Embeddings | Ollama support for privacy and speed |
GPU Acceleration | Works with any CUDA-capable GPU |
Duplicate Prevention | 90% similarity threshold prevents redundant saves |
TTL Management | 365-day expiry with automatic cleanup |
Fallback Chain | Ollama → Google → Hash (always available) |
Project Scoping | Search across all projects or project-specific |
Auto-Save Hook | Optional PostToolUse hook for automatic extraction |
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ MEMORY-MCP v3.8.0 │
└─────────────────────────────────────────────────────────────────┘
Agent/User
│
├──────────────────────────────────────┐
│ │
┌───▼────┐ ┌──────▼───────┐
│ Manual │ │ Auto-Save │
│ MCP │ │ Hook │
│ Tools │ │ (Optional) │
└───┬────┘ └──────┬───────┘
│ │
│ ┌───────────────────────▼──────────┐
│ │ LLM Judge (Gemini Flash) │
│ │ - Determines worthiness │
│ │ - Extracts category & tags │
│ └───────────────────────┬──────────┘
│ │
└──────────────┬───────────────────────┘
│
┌──────────▼──────────┐
│ Embedding Generation │
│ Primary: Ollama │
│ Fallback: Google │
│ Last: Hash-based │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Duplicate Check │
│ (90% similarity) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ LanceDB │
│ - 1024-dim vectors │
│ - BM25 FTS index │
│ - TTL (365 days) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Query Pipeline │
│ 1. Vector Search │
│ 2. FTS Search │
│ 3. RRF Fusion │
│ 4. Neural Rerank │
│ 5. TTL Filter │
└─────────────────────┘Quick Start
# Clone and setup
git clone https://github.com/wb200/memory-mcp.git
cd memory-mcp
uv sync
# Configure MCP client (add to your mcp.json)
{
"mcpServers": {
"memory": {
"command": "/path/to/memory-mcp/.venv/bin/python",
"args": ["/path/to/memory-mcp/server.py"],
"env": {
"GOOGLE_API_KEY": "your-api-key"
}
}
}
}
# Test it works
memory_health() # Should show system status
memory_save(content="Test memory", category="DEBUG")
memory_recall(query="test")Installation
Prerequisites
Python 3.11 or higher
uv package manager (recommended)
Ollama (optional, for local embeddings) OR Google API key
Step 1: Clone and Setup
git clone https://github.com/wb200/memory-mcp.git
cd memory-mcp
# Using uv (recommended)
uv syncStep 2: Install Ollama (Recommended for Privacy)
# Install Ollama
curl -fsSL https://ollama.ai/install.sh | sh
# Pull the embedding model
ollama pull qwen3-embedding:0.6b
# Start Ollama server
ollama serveWith GPU (systemd service):
# /etc/systemd/system/ollama.service
[Unit]
Description=Ollama LLM Service
After=network-online.target
[Service]
ExecStart=/usr/local/bin/ollama serve
Environment="CUDA_VISIBLE_DEVICES=0"
Environment="OLLAMA_NUM_GPU=all"
Restart=always
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now ollamaStep 3: Configure MCP Client
Add to your MCP configuration file:
Claude Code / Factory (~/.factory/mcp.json):
{
"mcpServers": {
"memory": {
"type": "stdio",
"command": "/path/to/memory-mcp/.venv/bin/python",
"args": ["/path/to/memory-mcp/server.py"],
"env": {
"EMBEDDING_PROVIDER": "ollama",
"EMBEDDING_MODEL": "qwen3-embedding:0.6b",
"EMBEDDING_DIM": "1024",
"OLLAMA_BASE_URL": "http://localhost:11434",
"GOOGLE_API_KEY": "${GOOGLE_API_KEY}",
"LANCEDB_MEMORY_PATH": "/home/youruser/.memory-mcp/lancedb-memory"
}
}
}
}Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"memory": {
"command": "/path/to/memory-mcp/.venv/bin/python",
"args": ["/path/to/memory-mcp/server.py"],
"env": {
"GOOGLE_API_KEY": "your-api-key"
}
}
}
}Configuration
Environment Variables
Variable | Default | Description |
|
| Database location |
|
|
|
|
| Embedding model name |
|
| Embedding dimensions |
|
| Ollama API endpoint |
| - | Google Gemini API key |
Server Configuration
These are set in the Config class in server.py:
Setting | Default | Description |
|
| LLM for summarization |
|
| Memory time-to-live |
|
| Duplicate similarity threshold |
|
| FTS weight in RRF fusion |
|
| Default results per query |
|
| Maximum results per query |
MCP Tools Reference
Overview
Tool | Description | Read-Only |
| Save a memory with semantic embedding | No |
| Search across ALL projects | Yes |
| Search in CURRENT project only | Yes |
| Delete a memory by ID | No |
| Update an existing memory | No |
| Get statistics by category/project | Yes |
| Get system health status | Yes |
memory_save
Save a new memory with automatic embedding and duplicate detection.
Parameters:
content(required): Memory contentcategory: One ofPATTERN,CONFIG,DEBUG,PERF,PREF,INSIGHT,API,AGENTtags: List of tags for categorizationsummarize: Use LLM to summarize verbose content
Example:
memory_save(
content="[DEBUG] - RuntimeError: CUDA out of memory solved with gradient_checkpointing=True. Context: Fine-tuning transformer. Rationale: Trades compute for memory.",
category="DEBUG",
tags=["pytorch", "cuda", "memory"]
)
# Response: Saved (ID: a1b2c3d4..., DEBUG)
# Tags: ['pytorch', 'cuda', 'memory']memory_recall
Search across all projects using hybrid search.
Parameters:
query(required): Search query (semantic + keywords)category: Optional category filterlimit: Max results (default 5, max 50)
Example:
memory_recall(
query="CUDA out of memory pytorch",
category="DEBUG",
limit=3
)
# Response: Found 2 memories (global, hybrid + neural rerank):
#
# [1] DEBUG (ID: a1b2c3d4...)
# RuntimeError: CUDA out of memory solved with gradient_checkpointing...
# Tags: pytorch, cuda, memory
# Similarity: 94%memory_recall_project
Same as memory_recall but scoped to current project only.
memory_delete
Delete a memory by full or partial ID.
Example:
memory_delete(memory_id="a1b2c3d4") # Full ID
memory_delete(memory_id="a1b2") # Partial prefix (must be unambiguous)memory_update
Update content, category, or tags of an existing memory.
Example:
memory_update(
memory_id="a1b2c3d4",
content="Updated content here",
category="CONFIG",
tags=["new", "tags"]
)memory_stats
Get memory statistics.
Example:
memory_stats()
# Response: === Memory Statistics (LanceDB) ===
# Total: 47 memories
# Database: 185.7 KB
# ...
# By Category:
# CONFIG: 15
# DEBUG: 12
# ...memory_health
Get system health and configuration status.
Example:
memory_health()
# Response: === Memory Health Status ===
# Total memories: 47
# Database size: 185.7 KB
# FTS index: ✓ BM25 enabled
# Vector index: ✓ IVF-PQ
# TTL: 365 days
# TTL cleanup: ✓ Active (every 24h)Hook System (Auto-Save)
The hook system enables automatic memory extraction from agent actions and memory recall at session start for context injection. This is optional but recommended for hands-free learning.
Hooks Overview
Hook Event | File | Trigger | Purpose |
PostToolUse |
| After Edit/Write/Bash/MultiEdit | Auto-save memory-worthy insights |
SessionStart |
| On startup, | Inject memory context at session start |
How They Work
1. memory-extractor.py (PostToolUse)
Triggers after tool executions (Edit, Write, Bash, MultiEdit, MCP tiger tools)
Analyzes the action using an LLM judge (Gemini Flash)
Extracts category, content, and tags if memory-worthy
Checks for duplicates (90% similarity threshold)
Saves automatically to the same LanceDB database
2. session_start_recall.py (SessionStart)
Triggers on session events:
startup,resume(/resume),clear(/clear),compactRetrieves memories for the current project from LanceDB
Generates a "Project Highlights" summary using Gemini
Outputs JSON with
additionalContextfield (injected into agent context)
Installation
For Factory/Droid users:
⭐ Recommended: Global Hooks Installation
To enable memory capture across all projects (not just memory-mcp):
Copy hooks to global Factory hooks directory:
cp /path/to/memory-mcp/.factory/hooks/memory-extractor.py ~/.factory/hooks/
cp /path/to/memory-mcp/.factory/hooks/session_start_recall.py ~/.factory/hooks/Configure in
~/.factory/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|Bash|MultiEdit|mcp__tiger__.*",
"hooks": [
{
"type": "command",
"command": "~/.factory/hooks/memory-extractor.py",
"timeout": 30
}
]
}
],
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
"command": "~/.factory/hooks/session_start_recall.py",
"timeout": 30
}
]
}
]
}
}Why Global Installation?
✅ Works everywhere - Captures memories from all your projects
✅ No configuration per project - Set up once, works forever
✅ Automatic project tagging - Each memory tagged with project_id (git remote or cwd)
✅ Centralized updates - Update hooks in one place
Alternative: Project-Specific Hooks (not recommended unless you only want memories from memory-mcp project):
Hooks are also in
.factory/hooks/within the projectUse absolute path:
/path/to/memory-mcp/.factory/hooks/memory-extractor.pyOnly triggers when working inside memory-mcp directory
Factory/Droid Hook Events Reference
Event | Matchers | When It Fires |
|
| New session, |
| Tool names (regex) | After any matched tool executes successfully |
| Tool names (regex) | Before tool execution (can block/modify) |
| N/A | When user submits a prompt (NOT on slash commands) |
| N/A | When agent finishes responding |
| N/A | When agent sends notifications |
Note:
/resumetriggersSessionStartwithresumematcher, NOTUserPromptSubmit. This is a common configuration mistake.
Project-Based Hooks
Hooks are stored in the project folder (version controlled):
memory-mcp/
├── .factory/
│ └── hooks/
│ ├── memory-extractor.py # Auto-save after tool use
│ └── session_start_recall.py # Memory recall at session start
└── server.pyThis approach:
Version controls hooks with the project
Makes configuration portable (no hardcoded paths)
Enables team sharing via git
LLM Judge Criteria
The judge saves memories ONLY when they match:
Bug fix with non-obvious cause/solution
New coding pattern or architecture insight
Configuration that took effort
Error resolution with reusable fix
Performance optimization
User preference explicitly stated
It SKIPS:
Simple file reads/listings
Trivial edits or formatting
Status checks
Actions without learning value
Memory Categories
Category | When to Use |
| Coding patterns, architectures, design decisions |
| Tool configurations, environment settings |
| Error resolutions, debugging techniques |
| Performance optimizations |
| User preferences, coding style |
| Cross-project learnings |
| LLM/external API usage patterns |
| Agent design patterns, workflows |
Hook Limits
Setting | Value | Description |
Rate Limit | 30s | Minimum time between extractions |
Timeout | 30s | Max execution time |
Context | 5 messages | Recent transcript context |
Hook Logs
Monitor hook activity:
tail -f ~/.factory/logs/memory-extractor.logSearch Technology
Hybrid Search Pipeline
Memory-MCP uses true hybrid search combining multiple retrieval methods:
Query
│
├─────────────────────────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Vector Search │ │ FTS Search │
│ (70% weight) │ │ (30% weight) │
│ Cosine similarity│ │ BM25 keywords │
└────────┬────────┘ └────────┬────────┘
│ │
└───────────┬─────────────┘
│
▼
┌──────────────────┐
│ RRF Fusion │
│ 1/(k + rank) │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Neural Reranking │
│ CrossEncoder │
│ mxbai-reranker │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ TTL Filter │
│ expires_at > NOW │
└────────┬─────────┘
│
▼
Top K ResultsComponents
Vector Search (70% weight)
1024-dimensional embeddings (qwen3-embedding or Gemini)
Cosine similarity
Captures semantic meaning
BM25 FTS (30% weight)
Tantivy-based full-text search
TF-IDF keyword matching
Catches exact phrases and rare terms
RRF Fusion
Reciprocal Rank Fusion combines results
Weighted scoring prevents either method dominating
Neural Reranking
CrossEncoder:
mixedbread-ai/mxbai-reranker-base-v2BEIR benchmark SOTA (reinforcement learning trained)
Improves relevance 10-15%
Performance
Operation | Time |
Embedding (GPU) | ~10ms |
Embedding (CPU) | ~30-50ms |
Vector Search | 20-30ms |
FTS Search | 2-5ms |
RRF Fusion | <1ms |
Neural Rerank | 20-50ms |
Total Recall | 50-130ms |
Memory Lifecycle
┌─────────────────────────────────────────────────────────────┐
│ CREATION │
├─────────────────────────────────────────────────────────────┤
│ Source: memory_save() or Auto-Save Hook │
│ ↓ │
│ Embedding Generation (Ollama → Google → Hash fallback) │
│ ↓ │
│ Duplicate Check (90% similarity threshold) │
│ ↓ │
│ Store to LanceDB with TTL (365 days) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ACTIVE (365 days) │
├─────────────────────────────────────────────────────────────┤
│ Available for recall │
│ TTL checked on each query │
│ Can be updated via memory_update() │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ EXPIRATION │
├─────────────────────────────────────────────────────────────┤
│ Background cleanup runs every 24 hours │
│ Expired memories deleted automatically │
└─────────────────────────────────────────────────────────────┘Usage Examples
Basic Usage
# Save a debugging insight
memory_save(
content="[DEBUG] - Python multiprocessing on macOS requires 'spawn' start method. Use: mp.set_start_method('spawn'). Context: ML training. Rationale: 'fork' causes CUDA issues.",
category="DEBUG",
tags=["python", "multiprocessing", "macos", "cuda"]
)
# Search for it later
memory_recall(query="multiprocessing macos cuda")
# Check system health
memory_health()With Category Filtering
# Only search CONFIG memories
memory_recall(query="database connection", category="CONFIG")Project-Specific Search
# Search only in current project
memory_recall_project(query="authentication pattern")Using Summarization
# Let LLM summarize verbose content
memory_save(
content="Very long error log with stack trace...",
category="DEBUG",
summarize=True # LLM extracts key insight
)Auto-Save Example
With the hook configured, after you fix a bug:
# You run: Edit file to fix ImportError
# Hook automatically saves:
# "[DEBUG] - ImportError: No module named 'xyz' fixed by adding to PYTHONPATH. Context: Package structure issue."Project ID Migration
If you have existing memories from before v3.7.0, you may have duplicate project IDs in different formats:
git@github.com:owner/repo.git(SSH)https://github.com/owner/repo.git(HTTPS)/home/user/projects/repo(path)
Run the migration script to normalize all git URLs:
# Preview changes (recommended first)
uv run migrate_project_ids.py --dry-run
# Apply migration
uv run migrate_project_ids.pyExample output:
2 memories: git@github.com:wb200/memory-mcp.git
-> github.com/wb200/memory-mcp
✓ Migration complete! Updated 2 memoriesAfter migration, all git URLs use canonical format: github.com/owner/repo
Note: Path-based project IDs (e.g., /home/user/projects/repo) are preserved for backward compatibility with legacy memories.
Testing
Run All Tests
cd memory-mcp
uv run pytest -vMCP Inspector Testing
Test the server interactively with the MCP Inspector:
# Start the server in a separate terminal
cd memory-mcp
uv run python server.py
# In another terminal, run the inspector
npx @modelcontextprotocol/inspector http://localhost:3000Or test via stdio:
cd memory-mcp
uv run python -c "
import asyncio
from server import mcp
async def test():
result = await mcp.tools['memory_health']()
print(result)
asyncio.run(test())
"Test Database
Tests use an isolated database separate from production:
Variable | Default Location |
|
|
|
|
The test database is automatically created and wiped before each test run. It's excluded from git via .gitignore.
Current Test Results
30 passed in ~23sTest Suites
Suite | Tests | Coverage |
TestMemorySave | 7 | Save validation, deduplication |
TestMemoryRecall | 6 | Search, filtering, project scope |
TestMemoryUpdate | 3 | Update operations |
TestMemoryDelete | 3 | Delete by ID, partial match |
TestMemoryStats | 1 | Statistics |
TestEmbeddings | 2 | Generation, similarity |
TestSummarization | 1 | LLM summarization |
TestConcurrency | 3 | Thread safety |
TestFullLifecycle | 1 | End-to-end CRUD |
TestHookIntegration | 2 | Hook configuration |
TestMCPConfig | 1 | Config validation |
Web Viewer
A beautiful, always-on browser interface for browsing your memory database with advanced filtering and search capabilities.
Features
🎨 Color-coded categories - Visual distinction between PATTERN, CONFIG, DEBUG, etc.
🔍 Dual search modes - Filter by project AND keyword simultaneously
📊 Pagination - Smooth navigation through large memory sets
🏷️ Tag display - See all tags and metadata at a glance
⚡ Real-time updates - Always reflects current database state
🌐 Project filtering - Quickly isolate memories from specific codebases
Quick Start (Manual)
# Install Flask (one-time)
uv add --group optional flask
# Run the viewer
uv run memory-viewer
# Access at http://localhost:5000⭐ Recommended: Always-On Service
Run the memory viewer as a persistent background service that:
✅ Survives terminal closures - No more accidentally killing the viewer
✅ Auto-starts on boot - Available immediately after system restart
✅ Auto-restarts on crash - Built-in systemd recovery
✅ Zero maintenance - Set it and forget it
✅ Integrated logging - All output captured in systemd journal
One-command setup:
# Install and start the service
./install-service.sh
# Enable 24/7 always-on mode (survives logout/reboot)
loginctl enable-linger $USERThat's it! Access your memories anytime at http://localhost:5000 🚀
Service Management
# Check status and uptime
systemctl --user status memory-viewer
# Restart after code updates
systemctl --user restart memory-viewer
# View real-time logs
journalctl --user -u memory-viewer -f
# Stop the service
systemctl --user stop memory-viewer
# Uninstall completely
./uninstall-service.shPerformance Impact
The always-on service is lightweight and designed for 24/7 operation:
Resource | Usage | Notes |
Memory | ~130MB | Flask app + Python runtime |
CPU | <1% idle | Only active during page loads |
Disk | Negligible | Reads from existing LanceDB |
Network | Local only | Binds to 127.0.0.1:5000 |
Advanced Configuration
See SERVICE.md for:
Custom port configuration
Production WSGI server setup (Gunicorn/uWSGI)
Troubleshooting service issues
Log rotation and monitoring
Security considerations
Why Use the Service vs Manual?
Scenario | Manual Run | Always-On Service |
Quick check | ✅ Perfect | 🔶 Overkill |
Daily use | 🔶 Annoying to restart | ✅ Always ready |
Shared machine | ❌ Stops on logout | ✅ Keeps running |
Development workflow | 🔶 Tab clutter | ✅ Clean workspace |
Team access | ❌ Unreliable | ✅ Guaranteed uptime |
Bottom line: If you check memories more than once a day, the service pays for itself in convenience.
Troubleshooting
"GOOGLE_API_KEY not found"
export GOOGLE_API_KEY="your-api-key"
# Or add to MCP config env section"Ollama connection refused"
# Start Ollama
ollama serve
# Or check systemd
sudo systemctl status ollama"Duplicate detected" too often
Lower the threshold in server.py:
dedup_threshold: float = 0.85 # Try 85% instead of 90%Hook not triggering
For PostToolUse hooks (memory-extractor):
Check logs:
tail -f ~/.factory/logs/memory-extractor.logVerify settings.json has correct
$FACTORY_PROJECT_DIRpathEnsure you're using tools that match the hook matcher (Edit|Write|Bash|MultiEdit)
For SessionStart hooks (session_start_recall):
Check debug log:
cat memory-mcp/.factory/hooks/hook-debug.logThe hook triggers on: startup,
/resume,/clear, compactVerify settings.json has
SessionStartevent with matcherstartup|resume|clear|compactEnsure hook outputs valid JSON with
hookSpecificOutput.additionalContextfield
Embedding dimension mismatch
Reset database (will lose existing memories):
rm -rf ~/.memory-mcp/lancedb-memoryHealth Check
Always start troubleshooting with:
memory_health()API Reference
Memory Schema
class Memory:
id: str # UUID
content: str # Memory text (FTS indexed)
vector: Vector(1024) # Semantic embedding
category: str # PATTERN|CONFIG|DEBUG|PERF|PREF|INSIGHT|API|AGENT
tags: str # JSON array: '["tag1", "tag2"]'
project_id: str # Git remote URL or cwd
user_id: str | None # Optional
created_at: str # ISO timestamp
updated_at: str # ISO timestamp
expires_at: str # ISO timestamp (TTL)Config Schema
@dataclass(frozen=True, slots=True)
class Config:
db_path: Path = Path.home() / ".memory-mcp" / "lancedb-memory"
table_name: str = "memories"
embedding_model: str = "qwen3-embedding:0.6b"
embedding_dim: int = 1024
embedding_provider: str = "ollama"
ollama_base_url: str = "http://localhost:11434"
llm_model: str = "gemini-3-flash-preview"
ttl_days: int = 365
dedup_threshold: float = 0.90
fts_weight: float = 0.3
default_limit: int = 5
max_limit: int = 50FAQ
Q: Can I use this without Ollama?
A: Yes, set EMBEDDING_PROVIDER=google and provide GOOGLE_API_KEY.
Q: Is GPU required?
A: No, but recommended. CPU embeddings are ~3x slower.
Q: What happens if all embedding providers fail?
A: Hash-based fallback ensures saves always work (reduced semantic quality).
Q: How do I backup my memories?
A: Copy ~/.memory-mcp/lancedb-memory/ directory.
Q: Can multiple agents share the same database?
A: Yes, LanceDB supports concurrent access.
Q: Is the hook required?
A: No, it's optional. You can use memory_save() manually.
Contributing
Fork the repository
Run tests:
uv run pytest -vFormat code:
uv run ruff format .Lint:
uv run ruff check .Submit PR
License
MIT License - See LICENSE file.
Acknowledgments
LanceDB - Vector database
Tantivy - Full-text search
Sentence-Transformers - CrossEncoder reranking
Ollama - Local embeddings
Google Gemini - LLM judge & embeddings
MCP - Model Context Protocol
Version History:
v3.8.0 - R.A.S.I.R. code quality improvements: fixed SQL LIKE wildcard injection, added secret file permissions validation, extracted shared models (
models.py) and utils (utils.py) for DRY, consolidated duplicate embedding normalization and git URL normalization, added Config validation with__post_init__, improved type hints, fixed all ruff violations. Documented global hooks installation for cross-project memory capture.v3.7.0 - Project ID normalization: git URLs now use canonical format (github.com/owner/repo), migration script for existing memories, eliminates duplicate project fragmentation
v3.6.0 - Always-on web viewer with systemd service support, linger mode for 24/7 availability, legacy project ID fallback for backward compatibility
v3.5.0 - Renamed MCP server from
droid-memorytomemory(agent-agnostic), fixedhookEventNamecamelCase bug, silent context injection (removed verbose stderr)v3.4.0 - Fixed hook configuration: SessionStart event (not UserPromptSubmit) for memory recall on
/resume, JSON output format for context injection, comprehensive hook documentationv3.3.0 - Project-based hooks, dual hooks (auto-save + session start recall)
v3.2.0 - SOTA reranker (mxbai-reranker-base-v2), path updates
v3.1.0 - Tantivy FTS, embedding cache, TTL cleanup
v3.0.0 - Ollama integration, 1024-dim embeddings
v2.0.0 - Hook system, LLM judge
v1.0.0 - Initial release
Available Tools
8 toolsmemory_deleteADestructiveIdempotent
Delete a memory by ID.
Args:
memory_id: The ID of the memory to delete (full or partial UUID)
| Name | Required | Description | Default |
|---|---|---|---|
| memory_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true. The description adds no additional behavioral context (e.g., irreversibility, error behavior). It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with no wasted words. The primary action is front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema and clear annotations, the description is mostly complete. Minor gaps (e.g., irreversibility) are hinted by annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning beyond the schema by specifying that memory_id can be a full or partial UUID. This helps the agent understand acceptable input formats.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Delete a memory by ID', using a specific verb and resource. This distinguishes it from sibling tools like memory_recall or memory_save.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives like memory_update or memory_recall. The agent must infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_healthARead-onlyIdempotent
Get memory system health status - indexes, database size, configuration.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, non-destructive, and idempotent behavior. The description adds value by specifying the content of the health status (indexes, database size, configuration), providing context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that efficiently conveys the tool's purpose without any wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (no parameters, rich annotations, and an output schema), the description provides sufficient information for an agent to understand what the tool does and what it returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters and 100% schema coverage, the description adds no parameter information. According to the rubric, baseline is 3 when schema coverage is high, which is appropriate here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Get') and resource ('memory system health status') with explicit sub-categories ('indexes, database size, configuration'). This clearly distinguishes it from sibling tools like memory_stats, which likely provides raw statistics rather than health status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as memory_stats. It does not mention any prerequisites, exclusions, or context that would help an agent decide to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_recallARead-onlyIdempotent
Hybrid search (vector + BM25) across ALL projects with neural reranking.
Args:
query: Search query - works with both keywords and semantic concepts
category: Optional filter: PATTERN, CONFIG, DEBUG, PERF, PREF, INSIGHT, API, AGENT
limit: Max results (default 5, max 50)
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| category | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint, and idempotentHint. The description adds context about the search method (hybrid, neural reranking) and scope (all projects), going beyond annotations. However, it does not mention any potential performance considerations or data staleness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is succinct with a clear purpose sentence followed by a structured list of parameter semantics. Every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not detail return values. It covers parameter semantics and search methodology. However, it lacks information on result ordering or whether pagination is supported.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description explains all three parameters: query (keywords and semantic concepts), category (list of valid filters), and limit (default and max). This adds significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool performs hybrid search (vector + BM25) with neural reranking across all projects. This is a specific verb-resource combination that distinguishes it from sibling tools like memory_recall_project.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for cross-project search ("across ALL projects") but does not explicitly state when to use this tool over memory_recall_project or provide exclusion criteria. No explicit when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_recall_projectARead-onlyIdempotent
Hybrid search in CURRENT project only with neural reranking.
Args:
query: Search query - works with both keywords and semantic concepts
category: Optional category filter
limit: Max results (default 5, max 50)
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| category | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true. The description adds key behavioral traits: hybrid search (keywords + semantic) and neural reranking, which go beyond annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the core purpose. It uses a clear Arg list format with no extraneous information. Every sentence is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present (not detailed here), return values need no explanation. The description adequately covers purpose, scope, and parameters. Minor gap: no explicit mention of how 'current project' is determined, but overall sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description meaningfully explains each parameter: 'query' works with keywords and semantic concepts, 'category' is optional, 'limit' has default 5 and max 50. This adds value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly defines the tool's purpose: 'Hybrid search in CURRENT project only with neural reranking.' This includes a specific verb (search), resource (project), and scope (current project). It distinguishes from sibling tools like 'memory_recall' (likely global) and others.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states the tool works in 'CURRENT project only,' guiding when to use it (within project context). It does not explicitly mention when not to use or name alternatives, but the sibling list implies 'memory_recall' for global search. Clear context is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_saveA
Save a memory with semantic embedding. Use after learning something valuable.
Args:
content: Memory content. Format: '[CATEGORY] - [insight]. Context: [where]. Rationale: [why]'
category: One of PATTERN, CONFIG, DEBUG, PERF, PREF, INSIGHT, API, AGENT
tags: Optional tags for categorization (auto-extracted if summarize=True)
summarize: Use LLM to intelligently summarize verbose content
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | ||
| category | No | INSIGHT | |
| tags | No | ||
| summarize | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds behavioral details beyond annotations: semantic embedding, auto-tag extraction with summarize. Does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise description with well-structured args list. Each sentence adds value, though could be more streamlined.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers usage, parameters, and key behavior. Output schema exists, so return values not needed. Adequate for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, description adds meaningful formatting guidance for content, lists category options, and explains tags/summarize behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states verb 'save' and resource 'memory', with specific context 'with semantic embedding'. Distinguishes from sibling tools like memory_delete and memory_recall.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides basic usage guidance ('Use after learning something valuable'), but lacks explicit when-not-to-use or comparisons to alternatives like memory_update.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_session_startARead-onlyIdempotent
Get project context at session start: recent memories + AI summary.
Call this at the start of a session to recall project-specific context.
Includes:
- Project Highlights summary (architecture, tech stack, setup, patterns)
- Last 10 memories for immediate context
Use this instead of manually recalling memories.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, non-destructive, idempotent behavior. The description adds valuable context about output contents: Project Highlights summary and last 10 memories. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise, with only 4 sentences. It is front-loaded with the main purpose and includes key details without wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema, the description adequately explains what the tool does, what it returns, and when to use it. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, so schema coverage is 100%. The description does not need to add parameter information. Per guidelines, 0 parameters baseline is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Get project context at session start: recent memories + AI summary.' It uses a specific verb-resource combination and distinguishes from siblings by specifying session start context, and explicitly advises using this instead of manual recall.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('Call this at the start of a session') and provides guidance to prefer it over manual recall. It is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsARead-onlyIdempotent
Get memory system statistics - total, by category, by project.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, indicating safe behavior. The description adds value by specifying that statistics include total, by category, and by project, which goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the purpose. It is efficient but not exceptionally structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and a simple stat retrieval purpose, the description is complete. The presence of an output schema covers return values, so no further detail is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, and schema coverage is 100%, so the description does not need to add parameter details. The absence of parameters is self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and the resource 'memory system statistics' with scope 'total, by category, by project'. This distinguishes it from siblings like memory_recall (retrieval) and memory_save (writing).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide any guidance on when to use this tool versus alternatives. No explicit context for usage or exclusions is mentioned, limiting its utility for selecting the right tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_updateAIdempotent
Update an existing memory.
Args:
memory_id: The ID of the memory to update (full or partial UUID)
content: New content (re-embeds if changed)
category: New category
tags: New tags (replaces existing)
| Name | Required | Description | Default |
|---|---|---|---|
| memory_id | Yes | ||
| content | No | ||
| category | No | ||
| tags | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds behavioral context beyond annotations: it notes that content 're-embeds if changed' and tags 'replaces existing', which are not in the idempotentHint or other annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: one sentence summary followed by a clear Args list. Every sentence is informative with no waste. Front-loaded with the core action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema and annotations, the description covers the main parameters and side effects. Minor gap: no mention of return values or errors, but the output schema likely handles that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description fully compensates by explaining each parameter's meaning and side effects (e.g., memory_id is ID, content triggers re-embedding, tags replace). This is highly valuable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Update an existing memory' with a specific verb and resource. The parameter list reinforces the purpose, and it is distinct from siblings like memory_delete or memory_save.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide explicit guidance on when to use this tool versus alternatives like memory_save or memory_delete. Usage is implied from the action, but no when-not-to or alternative references.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
8 tool updates
v3.8.0- First observed
memory_delete - First observed
memory_health - First observed
memory_recall - First observed
memory_recall_project - First observed
memory_save - First observed
memory_session_start - First observed
memory_stats - First observed
memory_update
TDQS
Each tool has a distinct purpose: delete, health, recall (all projects), recall (current project), save, session start, stats, update. The two recall tools are differentiated by scope, and no overlapping functionality exists.
All tools follow a consistent 'memory_<verb>' pattern in snake_case, with verbs like delete, recall, save, update. The compound 'session_start' still fits the pattern clearly.
8 tools is appropriate for a memory system, covering CRUD operations, search, health, stats, and session context. Each tool earns its place without being excessive.
Core CRUD is covered (save, recall, update, delete). Minor gaps: no direct retrieval of a single memory by ID (only recall with search) and no bulk operations. Agents can work around these gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Persistent memory for AI agents. Search, store, and recall across sessions.
Persistent memory for AI agents. Search and store durable facts, preferences and decisions.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceProvides long-term memory for LLMs via local SQLite storage with hybrid search (BM25, vectors, recency decay), enabling AI coding agents to persist and recall memories across sessions without cloud or API keys.53MIT
- AlicenseNot gradedqualityCmaintenanceProvides AI coding agents with persistent, graph-connected memory across projects, enabling cross-project context retrieval via synaptic connections and hybrid search.156MIT
- FlicenseNot gradedqualityAmaintenanceProvides persistent, local-first memory with knowledge graph and hybrid search for AI coding agents, reducing token usage by storing decisions, patterns, and codebase context.8-
- AlicenseNot gradedqualityDmaintenanceProvides long-term memory for AI coding agents, enabling them to remember, search, and organize information across sessions and platforms like Claude Code, ChatGPT, and Cursor.189MIT
Appeared in Searches
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/wb200/memory-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server