mem0-mcp-selfhosted
A self-hosted persistent memory MCP server for Claude Code that stores, searches, and manages memories across sessions using Qdrant (vector store), Neo4j (knowledge graph), and Ollama/Anthropic (LLMs).
Core Memory Operations
Add memories (
add_memory): Save text or conversation history with LLM-based fact extraction (async) or raw storage (sync); supports metadata, graph extraction, and user/agent/run scopingSearch memories (
search_memories): Semantic vector search with reranking, relevance thresholds, temporal anchoring (as_of), and domain/type filteringBrowse/fetch memories (
get_memories,get_memory): Page through all memories by scope or retrieve a specific memory by UUIDUpdate/delete memories (
update_memory,delete_memory,delete_all_memories): Modify or remove individual or bulk memories within a scope
Document Ingestion
Ingest PDFs and images (
add_document): Async extraction from digital/scanned PDFs and images (via OCR/vision), with page-level provenance chunking, fact extraction, and duplicate detection
Async Queue Management
Task status (
memory_task_status): Poll progress of queued ingestion tasks (pending, processing, done, failed, dead)Queue health (
memory_queue_status): View queue depth, worker liveness, and estimated drain time
Memory History & Provenance
Change history (
memory_history): Full timeline of ADD, UPDATE, SUPERSEDED, and DELETE events for any memory
Entity Management
List/delete entities (
list_entities,delete_entities): Discover users/agents/runs with stored memories; cascade-delete an entity and all associated memories
Knowledge Graph (Neo4j)
Search graph (
mcp_search_graph): Find entities by name/ID with their outgoing relationshipsGet entity relationships (
mcp_get_entity): Retrieve all bidirectional relationships for a named entity
Session Automation
Claude Code hooks automatically inject relevant memories at session start and save session summaries at session end
Flexibility
Supports fully local setups (Ollama for LLM + embeddings) or cloud (Anthropic/Gemini); Neo4j is optional; extensive environment variable configuration
Allows using Google's Gemini API for knowledge graph extraction and splitting in the memory system.
Integrates with Neo4j as a knowledge graph store for entity relationships, enabling graph-based memory features.
Enables fully local operation with Ollama for both embeddings (e.g., bge-m3) and as the main LLM, providing privacy and offline capabilities.
Click on "Deploy 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., "@mem0-mcp-selfhosted Remember that I use Hatch for Python packaging"
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.
mem0-mcp-selfhosted
Self-hosted mem0 MCP server for Claude Code. Run a complete memory server against self-hosted Qdrant + Neo4j + Ollama, with your choice of Anthropic (Claude) or Ollama as the main LLM.
Uses the mem0ai package directly as a library, supports both Claude's OAT token and fully local Ollama setups, and exposes 11 MCP tools for full memory management.
Prerequisites
Service | Required | Purpose |
Qdrant | Yes | Vector memory storage and search |
Ollama | Yes | Embedding generation ( |
Neo4j 5+ | Optional | Knowledge graph (entity relationships) |
Google API Key | Optional | Required only for |
Python >= 3.10 and uv.
Authentication: The default setup uses Claude (Anthropic) as the LLM for fact extraction. No API key needed, the server automatically uses your Claude Code session token. For fully local setups, set
MEM0_PROVIDER=ollama. See Authentication for advanced options.
Related MCP server: mem0-mcp
Quick Start
Default (Anthropic)
Add the MCP server globally (available across all projects):
claude mcp add --scope user --transport stdio mem0 \
--env MEM0_USER_ID=your-user-id \
-- uvx --from git+https://github.com/elvismdev/mem0-mcp-selfhosted.git mem0-mcp-selfhostedAll defaults work out of the box: Qdrant on localhost:6333, Ollama embeddings on localhost:11434 with bge-m3 (1024 dims). Override any default via --env (see Configuration).
uvx automatically downloads, installs, and runs the server in an isolated environment, no manual installation needed. Claude Code launches it on demand when the MCP connection starts.
The server auto-reads your OAT token from ~/.claude/.credentials.json, no manual token configuration needed.
Fully Local (Ollama)
For a fully local setup with no cloud dependencies, use Ollama for both the main LLM and embeddings:
claude mcp add --scope user --transport stdio mem0 \
--env MEM0_PROVIDER=ollama \
--env MEM0_LLM_MODEL=qwen3:14b \
--env MEM0_USER_ID=your-user-id \
-- uvx --from git+https://github.com/elvismdev/mem0-mcp-selfhosted.git mem0-mcp-selfhostedMEM0_PROVIDER=ollama cascades to both the main LLM and graph LLM providers. Same infrastructure defaults apply (Qdrant on localhost:6333, bge-m3 embeddings). Per-service overrides (e.g. MEM0_LLM_URL, MEM0_EMBED_URL) still work when needed.
Or add it to a single project by creating .mcp.json in the project root:
{
"mcpServers": {
"mem0": {
"command": "uvx",
"args": ["--from", "git+https://github.com/elvismdev/mem0-mcp-selfhosted.git", "mem0-mcp-selfhosted"],
"env": {
"MEM0_PROVIDER": "ollama",
"MEM0_LLM_MODEL": "qwen3:14b",
"MEM0_USER_ID": "your-user-id"
}
}
}
}Try It
Restart Claude Code, then:
> Search my memories for TypeScript preferences
> Remember that I prefer Hatch for Python packaging
> Show me all entities in my knowledge graphCLAUDE.md Integration
Add these rules to your project's CLAUDE.md (or ~/.claude/CLAUDE.md for global use) so Claude Code proactively uses memory tools throughout the session:
# MCP Servers
- **mem0**: Persistent memory across sessions. At the start of each session, `search_memories` for relevant context before asking the user to re-explain anything. Use `add_memory` whenever you discover project architecture, coding conventions, debugging insights, key decisions, or user preferences. Use `update_memory` when prior context changes. Save information like: "This project uses PostgreSQL with Prisma", "Tests run with pytest -v", "Auth uses JWT validated in middleware". When in doubt, save it, future sessions benefit from over-remembering.This gives Claude Code behavioral instructions to actively search and save memories during the session. For best results, combine with Claude Code Hooks, the CLAUDE.md rules tell Claude how to use memory tools mid-session, while hooks handle the automatic injection and saving at session boundaries.
Claude Code Hooks
Session hooks automate memory at session boundaries, injecting memories on startup and saving summaries on exit. This happens automatically without manual tool calls.
Hook | Event | What it does |
| SessionStart ( | Searches mem0 for project-relevant memories and injects them as |
| Stop | Reads the last ~3 user/assistant exchanges from the transcript and saves a summary to mem0 via |
Both hooks are non-fatal, if mem0 is unreachable or any error occurs, Claude Code continues normally.
Install
Install hooks into your project:
mem0-install-hooksOr install globally (all projects):
mem0-install-hooks --globalThis adds the hook entries to .claude/settings.json. The installer is idempotent, running it twice won't create duplicates.
How it works
On session start, the context hook searches mem0 with two queries (project architecture + recent session summaries), deduplicates by memory ID, and formats the results as numbered lines under a # mem0 Cross-Session Memory header. These are injected via the hook's additionalContext response field.
On session stop, the stop hook reads the JSONL transcript, extracts the last 6 user/assistant messages (a sliding window via bounded deque), builds a summary prompt, and calls memory.add(infer=True) to extract atomic facts. Graph is force-disabled in hooks to stay within the 15s/30s timeout budgets.
Entry points
Command | Function | Registered in |
|
| SessionStart hook |
|
| Stop hook |
|
| CLI installer |
Hooks + CLAUDE.md
Hooks and CLAUDE.md are complementary layers that work best together:
Layer | Role | When |
Hooks | Automated data flow, injects stored memories on startup, saves session summaries on exit | Session boundaries (start/stop) |
CLAUDE.md | Behavioral instructions, tells Claude to actively search and save memories during the session | Throughout the session |
Hooks alone give you passive recall (memories appear at startup) and passive saving (summaries saved at exit). CLAUDE.md instructions add active mid-session behavior, Claude searches for relevant memories when encountering new topics, and saves important discoveries immediately rather than waiting for session end.
For the best experience, use both. Hooks ensure memories flow in and out automatically at session boundaries, while CLAUDE.md ensures Claude actively engages with memory tools during the session.
Authentication
The server resolves an Anthropic token using a prioritized fallback chain:
Priority | Source | Details |
1 |
| Explicit, user-controlled |
2 |
| Auto-reads Claude Code's OAT token (zero-config) |
3 |
| Standard pay-per-use API key |
4 | Disabled | Warns and disables Anthropic LLM features |
In Claude Code, priority 2 always wins, the credentials file exists as long as you're logged in. This means ANTHROPIC_API_KEY (priority 3) is never reached. To override the OAT token in Claude Code, use MEM0_ANTHROPIC_TOKEN (priority 1). ANTHROPIC_API_KEY is only useful for non-Claude-Code deployments (Docker, CI, standalone).
OAT tokens (sk-ant-oat...) use your Claude subscription. The server automatically detects the token type and configures the SDK accordingly. OAT tokens are automatically refreshed before expiry: the server proactively checks the token lifetime and refreshes via the Anthropic OAuth endpoint when nearing expiry (default: 30 minutes). On authentication failures, a 3-step defensive strategy kicks in, piggybacking on Claude Code's credentials file, self-refreshing via OAuth, and wait-and-retry, so long-running sessions survive token rotation seamlessly.
API keys (sk-ant-api...) use standard pay-per-use billing.
Tools
Memory Tools (9 core)
Tool | Description |
| Store text or conversation history as memories. Supports |
| Semantic search with optional |
| List/filter memories (non-search). Supports |
| Fetch a single memory by UUID. |
| Replace memory text. Re-embeds and re-indexes in Qdrant. |
| Delete a single memory by UUID. |
| Bulk-delete all memories in a scope. |
| List users/agents/runs with memory counts. Uses Qdrant Facet API. |
| Cascade-delete an entity and all its memories. |
Graph Tools
Tool | Description |
| Search Neo4j entities by name substring. Returns entities + outgoing relationships. |
| Get all relationships for an entity (bidirectional: incoming + outgoing). |
Prompt
The server registers a memory_assistant MCP prompt that provides Claude with a quick-start guide for using the memory tools effectively.
Parameters
All tools use Pydantic Annotated[type, Field(description=...)] for self-documenting parameter schemas. Common patterns:
user_iddefaults toMEM0_USER_IDenv var when not providedenable_graphoverrides the defaultMEM0_ENABLE_GRAPHper-callfilterssupports structured operators:{"key": {"eq": "value"}},{"AND": [...]}All responses are JSON strings via
json.dumps(result, ensure_ascii=False)
Configuration
All configuration is via environment variables. Create a .env file or set them in your MCP config.
Authentication
Variable | Default | Description |
| -- | Anthropic OAT or API token (priority 1) |
| -- | Standard Anthropic API key (priority 3) |
|
| OAT identity headers: |
|
| Seconds before expiry to trigger proactive OAT token refresh |
LLM
Variable | Default | Description |
|
| Top-level provider ( |
| (MEM0_PROVIDER) | Main LLM provider: |
|
| Shared Ollama base URL. Cascades to |
| (per-provider) | Model for the selected LLM provider. Defaults to |
| (cascades) | Ollama base URL for the main LLM. Cascades: |
|
| Max tokens for LLM responses (Anthropic only) |
| (MEM0_PROVIDER) | Graph LLM provider ( |
| (cascades) | Ollama base URL for graph LLM. Cascades: |
| (varies) | Graph model. Inherits |
| -- | Google API key (required for |
|
| Contradiction LLM provider in |
| (provider-aware) | Contradiction model in |
|
| How long Ollama keeps the model in VRAM between calls (e.g., |
|
| Set to |
Embedder
Variable | Default | Description |
|
| Embedding provider ( |
|
| Embedding model name |
| (cascades) | Ollama URL for embeddings. Cascades: |
|
| Embedding vector dimensions |
Vector Store (Qdrant)
Variable | Default | Description |
|
| Qdrant REST API URL |
| -- | Qdrant API key (for Qdrant Cloud) |
|
| Store vectors on disk (reduces RAM, slower search) |
| (client default) | Qdrant REST API timeout in seconds (e.g., |
|
| Qdrant collection name |
Graph Store (Neo4j)
Variable | Default | Description |
|
| Enable graph memory (entity extraction to Neo4j) |
|
| Neo4j Bolt endpoint |
|
| Neo4j username |
|
| Neo4j password |
| -- | Neo4j database name (multi-database setups) |
| -- | Custom Neo4j base label for node type grouping |
|
| Embedding similarity threshold for node matching |
Server
Variable | Default | Description |
|
| Transport: |
|
| Host for SSE/HTTP transports |
|
| Port for SSE/HTTP transports |
|
| Default user ID for memory scoping |
|
| Logging level ( |
| -- | SQLite path for memory change history |
Architecture
Claude Code
|
├── MCP stdio/SSE/streamable-http
│ |
│ ├── env.py ← Centralized env var readers (whitespace-safe)
│ ├── auth.py ← Hybrid token fallback chain + OAT self-refresh
│ ├── llm_anthropic.py ← Custom Anthropic LLM provider (OAT + structured outputs)
│ ├── llm_ollama.py ← Custom Ollama LLM provider (restored tool-calling)
│ ├── config.py ← Env vars → MemoryConfig dict (provider + URL cascades)
│ ├── helpers.py ← Error wrapper, concurrency lock, safe bulk-delete, monkey-patches
│ ├── graph_tools.py ← Direct Neo4j Cypher queries (lazy driver)
│ ├── llm_router.py ← Split-model graph LLM router (gemini_split)
│ ├── __init__.py ← Telemetry suppression (before any mem0 import)
│ └── server.py ← FastMCP orchestrator (11 tools + prompt)
│ |
│ ├── mem0ai Memory class
│ │ ├── Vector: LLM fact extraction → Ollama embed → Qdrant
│ │ └── Graph: LLM entity extraction (tool calls) → Neo4j
│ |
│ └── Infrastructure
│ ├── Qdrant ← Vector store
│ ├── Ollama ← Embeddings
│ ├── Neo4j ← Knowledge graph (optional)
│ └── Anthropic/Ollama ← Main LLM (configurable)
|
└── Session Hooks (subprocess, not MCP)
|
└── hooks.py ← Cross-session memory (SessionStart + Stop hooks)
├── context_main() → Injects memories as additionalContext on startup/compact
├── stop_main() → Saves session summary to mem0 on exit
└── install_main() → CLI to patch .claude/settings.jsonGraph Memory & Quota
Graph memory is disabled by default (MEM0_ENABLE_GRAPH=false) to protect your Claude quota. Each add_memory with graph enabled triggers 3 additional LLM calls for entity extraction, relationship generation, and conflict resolution.
Using Ollama for Graph Operations
To eliminate Claude quota usage for graph ops, use a local Ollama model:
MEM0_ENABLE_GRAPH=true
MEM0_GRAPH_LLM_PROVIDER=ollama
MEM0_GRAPH_LLM_MODEL=qwen3:14bQwen3:14b has 0.971 tool-calling F1 (nearly matching GPT-4's 0.974) and runs in ~7-8GB VRAM with Q4_K_M quantization.
Using Gemini for Graph Operations
Google's Gemini 2.5 Flash Lite is the cheapest option for graph ops while maintaining strong entity extraction accuracy:
MEM0_ENABLE_GRAPH=true
MEM0_GRAPH_LLM_PROVIDER=gemini
MEM0_GRAPH_LLM_MODEL=gemini-2.5-flash-lite
GOOGLE_API_KEY=your-google-api-keyUsing Split-Model for Best Accuracy
The gemini_split provider routes graph pipeline calls to different LLMs based on the operation. Entity extraction (Calls 1 & 2) goes to Gemini for speed and cost; contradiction detection (Call 3) goes to Claude for accuracy.
MEM0_ENABLE_GRAPH=true
MEM0_GRAPH_LLM_PROVIDER=gemini_split
GOOGLE_API_KEY=your-google-api-key
MEM0_GRAPH_CONTRADICTION_LLM_PROVIDER=anthropic
MEM0_GRAPH_CONTRADICTION_LLM_MODEL=claude-opus-4-6Benchmark results across 248 test cases: Gemini scores 85.4% on entity extraction (vs Claude's 79.1%), while Claude scores 100% on contradiction detection (vs Gemini's 80%). The split-model combines the best of both.
Transport Modes
Mode | Use Case | Config |
| Claude Code integration |
|
| Legacy remote clients |
|
| Modern remote clients |
|
For remote deployments, MCP SDK >= 1.23.0 enables DNS rebinding protection by default.
DeepMem0 Vault — client authentication
Anything that can reach streamable-http can read every memory. The vault is a
companion service that issues bearer tokens for the MCP and gives an admin a UI
to manage them.
UI admin (deepmem0-vault, :8080) ──writes──┐
├── vault.db (SQLite WAL, one absolute path)
MCP (:8081) ── BearerTokenMiddleware ───────┘ (verify + touch)Kill switch — MEM0_REQUIRE_AUTH:
Mode | Behavior |
| Delegates without opening the vault. Today's behavior, byte for byte. |
| Verifies every request, touches |
| Unauthorized requests get |
A typo (MEM0_REQUIRE_AUTH=true) raises at boot instead of silently disabling auth.
Setup:
pip install -e ".[vault]" # UI deps; the gate itself needs none
export VAULT_SECRET_KEY=$(python -c 'import secrets; print(secrets.token_urlsafe(48))')
export MEM0_VAULT_DB_PATH=~/.mem0/vault.db # same path in both services
deepmem0-vault bootstrap-admin # explicit, idempotent, never at boot
deepmem0-vault # serve the UI on :8080Then create a user, issue a token, and point a client at it:
claude mcp add --transport http deepmem0 http://localhost:8081/mcp \
--header "Authorization: Bearer dm0_..."Rules that are enforced, not documented: the plaintext token appears in
exactly one HTTP response and is never stored (only sha256 + a 12-char
prefix); every mutation and its audit row share one transaction; rotation
issues a successor and leaves the old token alive for a grace window
(VAULT_TOKEN_GRACE_HOURS, default 24) instead of causing an outage; revocation
applies to new requests, and every MCP tool call is a new request.
Promote shadow → on on positive evidence, and let the vault decide:
deepmem0-vault promotion-check --window-hours 72 # exit 0 = ready, 1 = notEvery ACTIVE token is the inventory — no separate list to keep in sync. The
check is ready only when each of them authorized inside the window AND no
request was denied. Silence is not evidence: a token nobody used is
indistinguishable from a client that would start taking 401s. The same readout
is a panel on the dashboard. Both read durable counters (tokens.use_count,
the auth_denials table), not throttled log lines that vanish on restart.
Per-tool authorization. Tokens carry an optional mem0_user_id. When set,
every one of the 15 tools consults it, under a policy declared in
TOOL_SCOPE_POLICY and enforced by a completeness test (tool #16 cannot ship
without a decision):
Policy | Tools | With a bound token |
| add_memory, add_document, search_memories, get_memories, delete_all_memories, delete_entities | the binding wins; a different |
| get_memory, memory_history, update_memory, delete_memory, memory_task_status | the record's owner decides; someone else's id and a nonexistent id give the same answer |
| list_entities | the enumeration is narrowed to the bound scope |
| memory_queue_status, mcp_search_graph, mcp_get_entity | refused — they report on the whole server |
Sessions are bound to the credential that opened them, so a leaked MCP session
id cannot be reused by a different token. Every token issued today has an empty
mem0_user_id, so all of this is inert until you bind one.
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run unit tests
python3 -m pytest tests/unit/ -v
# Run contract tests (validates mem0ai internal API assumptions)
python3 -m pytest tests/contract/ -v
# Run integration tests (requires live Qdrant + Neo4j + Ollama)
python3 -m pytest tests/integration/ -v
# Run all tests
python3 -m pytest tests/ -vTest Structure
tests/unit/-- Pure unit tests with mocked dependencies (env, auth, config, config matrix, concurrency, MCP protocol, helpers, hooks, LLM providers, graph tools, LLM router, server)tests/contract/-- Validates assumptions about mem0ai internals (schema detection invariant,vector_store.clientaccess path,LlmFactoryregistration idempotency)tests/integration/-- Live infrastructure tests (memory lifecycle, graph ops, bulk operations, hooks) against real Qdrant + Neo4j + Ollama. Marked with@pytest.mark.integration.
Contract tests catch breaking changes in mem0ai upgrades before they reach production.
Telemetry
All mem0ai telemetry is suppressed. os.environ["MEM0_TELEMETRY"] = "false" is set at package import time, before any mem0 module is loaded. No PostHog events are sent.
License
MIT
Available Tools
15 toolsadd_documentA
Ingest a PDF or image asynchronously: extract text per page (digital PDF via poppler; scanned pages and images via a local vision model), chunk, and extract memorable facts with document/page provenance.
Returns immediately with {"status": "queued", task_id, pages,
chunks_estimate, estimated_wait_s} — a large document takes many
minutes; poll memory_task_status(task_id) for chunks_done progress and
the final memory_ids. Re-submitting the same file returns
{"status": "already_ingested"} unless force=true. There is NO
synchronous fallback: if the queue is unavailable the call errors.
Inputs: file_path (required), force, infer, run_id, +5 more. Returns: result
add_memoryA
Store a new memory. Requires at least one of user_id, agent_id, or run_id.
Response contract (never a bare list):
- {"status": "queued", "task_id", "submitted_at", "queue_depth", "estimated_wait_s"}
— infer=true path; extraction runs in background, poll memory_task_status.
- {"status": "stored", "memory_ids": [...], "results": [...]}
— synchronous path; empty memory_ids carries "reason": "no_new_facts".
- {"error": ...} — failure.
Inputs: text (required), infer, run_id, user_id, +4 more. Returns: result
delete_all_memoriesA
Bulk-delete all memories in the given scope. Requires at least one filter.
NEVER calls memory.delete_all() — uses safe bulk-delete instead.
Inputs: run_id, user_id, agent_id. Returns: result
delete_entitiesA
Delete an entity and cascade-delete all its memories.
Functionally equivalent to delete_all_memories in self-hosted mode.
Inputs: run_id, user_id, agent_id. Returns: result
delete_memoryB
Delete a single memory.
Inputs: memory_id (required). Returns: result
get_memoriesA
Page through memories using filters instead of search.
Inputs: limit, run_id, user_id, agent_id. Returns: result
get_memoryB
Fetch a single memory by its ID.
Inputs: memory_id (required). Returns: result
list_entitiesB
List which users/agents/runs currently hold memories.
Uses Qdrant Facet API (v1.12+) for server-side aggregation, with scroll+dedupe fallback for older versions.
Inputs: no named parameters. Returns: result
mcp_get_entityA
Get all relationships for a specific entity (bidirectional).
Inputs: name (required). Returns: result
mcp_search_graphA
Search entities by name/id substring matching in Neo4j knowledge graph.
Inputs: query (required). Returns: result
memory_historyA
Full change timeline of a memory: ADD, UPDATE (old vs new text), SUPERSEDED (which fact replaced it) and DELETE events, oldest first.
Inputs: memory_id (required). Returns: result
memory_queue_statusA
Health of the async ingest queue: depth (jobs waiting or running), per-status counts, age of the oldest pending job, estimated drain time, and whether the background worker is alive.
Inputs: no named parameters. Returns: result
memory_task_statusA
Status of an asynchronous add_memory task.
States: pending | processing | done | failed_retryable | dead.
When done, ``result.memory_ids`` lists the memories created/updated
(fetch them with get_memory) and ``result.events`` includes any
SUPERSEDED markings. ``last_error`` explains failed/dead tasks.
Inputs: task_id (required). Returns: result
search_memoriesB
Semantic search across existing memories.
Inputs: query (required), as_of, limit, domain, +10 more. Returns: result
update_memoryA
Update an existing memory's text.
ASYNCHRONOUS by default (when MEM0_ASYNC_INGEST != false): validates the
memory exists, then returns {"status": "queued", "task_id", ...} immediately
while the re-embed + metadata re-classification (a slow llama3.1:8b call) run in
the background worker — so the call never times out the client. Poll
memory_task_status(task_id) for the result (memory_id / UPDATE event);
memory_history(memory_id) shows the old-vs-new diff. An identical re-submit
while the job is still active returns the same task_id (no double-apply). Set
MEM0_ASYNC_INGEST=false for the synchronous path.
Inputs: text (required), memory_id (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 15 tools
Most tools are clearly distinct (add_memory vs get_memory vs delete_memory, etc.). However, delete_entities and delete_all_memories are noted as functionally equivalent in self-hosted mode, causing some overlap. Also, mcp_get_entity and mcp_search_graph could be confused for entity lookups.
Many tools follow verb_noun pattern (add_memory, get_memory, delete_memory), but some use noun_first (memory_history, memory_queue_status) and two are prefixed with 'mcp_' (mcp_get_entity, mcp_search_graph), breaking consistency. Overall readable but mixed.
15 tools is well-scoped for a memory server. It covers CRUD, search, history, async task management, entity operations, and document ingestion without excess.
Core memory operations are fully covered (add, get, update, delete, search, history). Entity management and async task monitoring are included. Minor gap: no task cancellation tool. Also, delete_entities is redundant with delete_all_memories.
Maintenance
Related MCP Connectors
Private persistent memory for Claude, ChatGPT & Gemini via MCP - semantic search, zero-code setup.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Self-hosted AI workspace: semantic RAG document search, long-term memory, and AI chat via MCP.
Persistent AI memory shared across Claude, ChatGPT, coding agents, and compatible MCP clients.
Related MCP Servers
- AlicenseAqualityDmaintenanceSelf-hosted mem0 MCP server for Claude Code. Run a complete memory server against self-hosted Qdrant + Neo4j + Ollama while using Claude as the main LLM.11112MIT

mem0-mcpofficial
AlicenseAqualityDmaintenanceSelf-hosted Mem0 MCP server integrating Qdrant, Neo4j, and Ollama for semantic memory search, graph entity relationships, and memory management via OpenMemory API.64MIT- AlicenseNot gradedqualityCmaintenanceA persistent memory MCP server for Claude Code that enables long-term recall across sessions via hybrid search, code intelligence, and tools for reading/writing memory.18 npm5MIT
- AlicenseNot gradedqualityDmaintenanceA fully local, self-hosted memory server for MCP clients (Claude Code, Cursor, etc.) that provides persistent memory storage with semantic search, using local embeddings and a local Qdrant vector store.MIT