mem0-mcp-selfhosted
Servidor MCP mem0 autoalojado para Claude Code. Ejecuta un servidor de memoria completo contra Qdrant + Neo4j + Ollama autoalojados mientras usas Claude como LLM principal.
Documentación
mem0-mcp-selfhosted
Servidor MCP de mem0 autoalojado para Claude Code. Ejecuta un servidor de memoria completo contra Qdrant + Neo4j + Ollama autoalojados, con tu elección de Anthropic (Claude) u Ollama como LLM principal.
Utiliza el paquete mem0ai directamente como biblioteca, admite tanto el token OAT de Claude como configuraciones totalmente locales con Ollama, y expone 11 herramientas MCP para la gestión completa de memoria.
Prerrequisitos
| Servicio | Requerido | Propósito |
|---|---|---|
| Qdrant | Sí | Almacenamiento y búsqueda de memoria vectorial |
| Ollama | Sí | Generación de embeddings (bge-m3) y opcionalmente LLM local |
| Neo4j 5+ | Opcional | Grafo de conocimiento (relaciones entre entidades) |
| Clave API de Google | Opcional | Requerida solo para los proveedores de grafo gemini/gemini_split |
Python >= 3.10 y uv.
Autenticación: La configuración predeterminada usa Claude (Anthropic) como LLM para la extracción de hechos. No se necesita clave API, el servidor usa automáticamente el token de sesión de Claude Code. Para configuraciones totalmente locales, establece
MEM0_PROVIDER=ollama. Consulta Autenticación para opciones avanzadas.
Inicio Rápido
Predeterminado (Anthropic)
Agrega el servidor MCP globalmente (disponible en todos los proyectos):
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-selfhosted
Todos los valores predeterminados funcionan de inmediato: Qdrant en localhost:6333, embeddings de Ollama en localhost:11434 con bge-m3 (1024 dimensiones). Anula cualquier valor predeterminado mediante --env (consulta Configuración).
uvx descarga, instala y ejecuta automáticamente el servidor en un entorno aislado, sin necesidad de instalación manual. Claude Code lo inicia bajo demanda cuando comienza la conexión MCP.
El servidor lee automáticamente tu token OAT desde ~/.claude/.credentials.json, sin necesidad de configuración manual de token.
Totalmente Local (Ollama)
Para una configuración totalmente local sin dependencias en la nube, usa Ollama tanto para el LLM principal como para los 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-selfhosted
MEM0_PROVIDER=ollama se propaga tanto al LLM principal como a los proveedores de LLM de grafo. Se aplican los mismos valores predeterminados de infraestructura (Qdrant en localhost:6333, embeddings de bge-m3). Las anulaciones por servicio (p. ej., MEM0_LLM_URL, MEM0_EMBED_URL) siguen funcionando cuando se necesitan.
O agrégalo a un solo proyecto creando .mcp.json en la raíz del proyecto:
{
"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"
}
}
}
}
Pruébalo
Reinicia Claude Code y luego:
> Search my memories for TypeScript preferences
> Remember that I prefer Hatch for Python packaging
> Show me all entities in my knowledge graph
Integración con CLAUDE.md
Agrega estas reglas al CLAUDE.md de tu proyecto (o ~/.claude/CLAUDE.md para uso global) para que Claude Code use proactivamente las herramientas de memoria durante toda la sesión:
# 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.
Esto le da a Claude Code instrucciones de comportamiento para buscar y guardar memorias activamente durante la sesión. Para mejores resultados, combínalo con Claude Code Hooks: las reglas de CLAUDE.md le indican a Claude cómo usar las herramientas de memoria a mitad de sesión, mientras que los hooks manejan la inyección y el guardado automáticos en los límites de la sesión.
Claude Code Hooks
Los hooks de sesión automatizan la memoria en los límites de la sesión, inyectando memorias al inicio y guardando resúmenes al salir. Esto ocurre automáticamente sin llamadas manuales a herramientas.
| Hook | Evento | Qué hace |
|---|---|---|
mem0-hook-context | SessionStart (startup, compact) | Busca en mem0 memorias relevantes al proyecto y las inyecta como additionalContext |
mem0-hook-stop | Stop | Lee los últimos ~3 intercambios usuario/asistente de la transcripción y guarda un resumen en mem0 mediante infer=True |
Ambos hooks no son fatales; si mem0 no está disponible o ocurre cualquier error, Claude Code continúa normalmente.
Instalación
Instala los hooks en tu proyecto:
mem0-install-hooks
O instala globalmente (todos los proyectos):
mem0-install-hooks --global
Esto agrega las entradas de hook a .claude/settings.json. El instalador es idempotente; ejecutarlo dos veces no crea duplicados.
Cómo funciona
Al iniciar la sesión, el hook de contexto busca en mem0 con dos consultas (arquitectura del proyecto + resúmenes de sesiones recientes), deduplica por ID de memoria y formatea los resultados como líneas numeradas bajo un encabezado # mem0 Cross-Session Memory. Se inyectan mediante el campo de respuesta additionalContext del hook.
Al detener la sesión, el hook de detención lee la transcripción JSONL, extrae los últimos 6 mensajes usuario/asistente (una ventana deslizante mediante deque acotado), construye un prompt de resumen y llama a memory.add(infer=True) para extraer hechos atómicos. El grafo está deshabilitado por fuerza en los hooks para mantenerse dentro de los presupuestos de tiempo de 15s/30s.
Puntos de entrada
| Comando | Función | Registrado en pyproject.toml |
|---|---|---|
mem0-hook-context | hooks:context_main | Hook SessionStart |
mem0-hook-stop | hooks:stop_main | Hook Stop |
mem0-install-hooks | hooks:install_main | Instalador CLI |
Hooks + CLAUDE.md
Los hooks y CLAUDE.md son capas complementarias que funcionan mejor juntos:
| Capa | Rol | Cuándo |
|---|---|---|
| Hooks | Flujo de datos automatizado, inyecta memorias almacenadas al inicio, guarda resúmenes de sesión al salir | Límites de sesión (inicio/detención) |
| CLAUDE.md | Instrucciones de comportamiento, le indica a Claude buscar y guardar memorias activamente durante la sesión | Durante toda la sesión |
Solo los hooks te dan recuperación pasiva (las memorias aparecen al inicio) y guardado pasivo (los resúmenes se guardan al salir). Las instrucciones de CLAUDE.md agregan comportamiento activo a mitad de sesión: Claude busca memorias relevantes al encontrar nuevos temas y guarda descubrimientos importantes de inmediato en lugar de esperar al final de la sesión.
Para la mejor experiencia, usa ambos. Los hooks aseguran que las memorias fluyan automáticamente en los límites de la sesión, mientras que CLAUDE.md asegura que Claude interactúe activamente con las herramientas de memoria durante la sesión.
Autenticación
El servidor resuelve un token de Anthropic usando una cadena de respaldo priorizada:
| Prioridad | Fuente | Detalles |
|---|---|---|
| 1 | Variable de entorno MEM0_ANTHROPIC_TOKEN | Explícita, controlada por el usuario |
| 2 | ~/.claude/.credentials.json | Lee automáticamente el token OAT de Claude Code (configuración cero) |
| 3 | Variable de entorno ANTHROPIC_API_KEY | Clave API estándar de pago por uso |
| 4 | Deshabilitado | Advierte y deshabilita las funciones LLM de Anthropic |
En Claude Code, la prioridad 2 siempre gana: el archivo de credenciales existe mientras estés conectado. Esto significa que ANTHROPIC_API_KEY (prioridad 3) nunca se alcanza. Para anular el token OAT en Claude Code, usa MEM0_ANTHROPIC_TOKEN (prioridad 1). ANTHROPIC_API_KEY solo es útil para implementaciones fuera de Claude Code (Docker, CI, independiente).
Tokens OAT (sk-ant-oat...) usan tu suscripción de Claude. El servidor detecta automáticamente el tipo de token y configura el SDK en consecuencia. Los tokens OAT se renuevan automáticamente antes de expirar: el servidor verifica proactivamente la vida útil del token y lo renueva mediante el endpoint OAuth de Anthropic cuando se acerca la expiración (predeterminado: 30 minutos). Ante fallos de autenticación, se activa una estrategia defensiva de 3 pasos: aprovechar el archivo de credenciales de Claude Code, auto-renovación mediante OAuth y esperar y reintentar, para que las sesiones de larga duración sobrevivan a la rotación de tokens sin problemas.
Claves API (sk-ant-api...) usan facturación estándar de pago por uso.
Herramientas
Herramientas de Memoria (9 principales)
| Herramienta | Descripción |
|---|---|
add_memory | Almacena texto o historial de conversación como memorias. Admite enable_graph, infer, metadata. |
search_memories | Búsqueda semántica con filters, threshold, rerank, enable_graph opcionales. |
get_memories | Lista/filtra memorias (sin búsqueda). Admite limit y filtros de alcance. |
get_memory | Obtiene una sola memoria por UUID. |
update_memory | Reemplaza el texto de una memoria. Re-embediza y re-indexa en Qdrant. |
delete_memory | Elimina una sola memoria por UUID. |
delete_all_memories | Elimina en masa todas las memorias en un alcance. |
list_entities | Lista usuarios/agentes/ejecuciones con conteos de memoria. Usa la API Facet de Qdrant. |
delete_entities | Elimina en cascada una entidad y todas sus memorias. |
Herramientas de Grafo
| Herramienta | Descripción |
|---|---|
search_graph | Busca entidades de Neo4j por subcadena de nombre. Devuelve entidades + relaciones salientes. |
get_entity | Obtiene todas las relaciones de una entidad (bidireccional: entrantes + salientes). |
Prompt
El servidor registra un prompt MCP memory_assistant que proporciona a Claude una guía de inicio rápido para usar las herramientas de memoria de manera efectiva.
Parámetros
Todas las herramientas usan Annotated[type, Field(description=...)] de Pydantic para esquemas de parámetros autodocumentados. Patrones comunes:
user_idusa por defecto la variable de entornoMEM0_USER_IDcuando no se proporcionaenable_graphanula elMEM0_ENABLE_GRAPHpredeterminado por llamadafiltersadmite operadores estructurados:{"key": {"eq": "value"}},{"AND": [...]}- Todas las respuestas son cadenas JSON mediante
json.dumps(result, ensure_ascii=False)
Configuración
Toda la configuración es mediante variables de entorno. Crea un archivo .env o establécela en tu configuración MCP.
Autenticación
| Variable | Predeterminado | Descripción |
|---|---|---|
MEM0_ANTHROPIC_TOKEN | -- | Token OAT o API de Anthropic (prioridad 1) |
ANTHROPIC_API_KEY | -- | Clave API estándar de Anthropic (prioridad 3) |
MEM0_OAT_HEADERS | auto | Encabezados de identidad OAT: auto o none |
MEM0_OAT_REFRESH_THRESHOLD_SECONDS | 1800 | Segundos antes de la expiración para activar la renovación proactiva del token OAT |
LLM
| Variable | Predeterminado | Descripción |
|---|---|---|
MEM0_PROVIDER | anthropic | Proveedor de nivel superior (anthropic o ollama). Se propaga a MEM0_LLM_PROVIDER y MEM0_GRAPH_LLM_PROVIDER cuando no están establecidos. No afecta a MEM0_EMBED_PROVIDER. |
MEM0_LLM_PROVIDER | (MEM0_PROVIDER) | Proveedor LLM principal: anthropic o ollama. Hereda de MEM0_PROVIDER cuando no está establecido. |
MEM0_OLLAMA_URL | http://localhost:11434 | URL base compartida de Ollama. Se propaga a MEM0_LLM_URL, MEM0_EMBED_URL y MEM0_GRAPH_LLM_URL cuando no están establecidos. |
MEM0_LLM_MODEL | (por proveedor) | Modelo para el proveedor LLM seleccionado. Usa por defecto claude-opus-4-6 para Anthropic, qwen3:14b para Ollama |
MEM0_LLM_URL | (se propaga) | URL base de Ollama para el LLM principal. Propagación: MEM0_LLM_URL → MEM0_OLLAMA_URL → http://localhost:11434. Solo se usa cuando MEM0_LLM_PROVIDER=ollama |
MEM0_LLM_MAX_TOKENS | 16384 | Máximo de tokens para respuestas LLM (solo Anthropic) |
MEM0_GRAPH_LLM_PROVIDER | (MEM0_PROVIDER) | Proveedor LLM de grafo (anthropic, anthropic_oat, ollama, gemini, gemini_split). Hereda de MEM0_PROVIDER cuando no está establecido. |
MEM0_GRAPH_LLM_URL | (se propaga) | URL base de Ollama para LLM de grafo. Propagación: MEM0_GRAPH_LLM_URL → MEM0_LLM_URL → MEM0_OLLAMA_URL → http://localhost:11434 |
MEM0_GRAPH_LLM_MODEL | (varía) | Modelo de grafo. Hereda MEM0_LLM_MODEL para anthropic/ollama; usa por defecto gemini-2.5-flash-lite para gemini/gemini_split |
GOOGLE_API_KEY | -- | Clave API de Google (requerida para los proveedores de grafo gemini/gemini_split) |
MEM0_GRAPH_CONTRADICTION_LLM_PROVIDER | anthropic | Proveedor LLM de contradicción en modo gemini_split (anthropic, anthropic_oat, ollama) |
MEM0_GRAPH_CONTRADICTION_LLM_MODEL | (según proveedor) | Modelo de contradicción en modo gemini_split. Usa por defecto claude-opus-4-6 para proveedores anthropic/anthropic_oat; hereda MEM0_LLM_MODEL para otros. |
MEM0_OLLAMA_KEEP_ALIVE | 30m | Cuánto tiempo mantiene Ollama el modelo en VRAM entre llamadas (p. ej., 1h, 5m). Evita la descarga del modelo durante pipelines de grafo de múltiples llamadas |
MEM0_OLLAMA_THINK | false | Establecer en true para re-habilitar el modo de pensamiento qwen3 (deshabilitado por defecto para prevenir la colisión <think> + format:"json") |
Embedder
| Variable | Por defecto | Descripción |
|---|---|---|
MEM0_EMBED_PROVIDER | ollama | Proveedor de embeddings (ollama o openai) |
MEM0_EMBED_MODEL | bge-m3 | Nombre del modelo de embeddings |
MEM0_EMBED_URL | (en cascada) | URL de Ollama para embeddings. En cascada: MEM0_EMBED_URL → MEM0_OLLAMA_URL → http://localhost:11434 |
MEM0_EMBED_DIMS | 1024 | Dimensiones del vector de embeddings |
Almacén de vectores (Qdrant)
| Variable | Por defecto | Descripción |
|---|---|---|
MEM0_QDRANT_URL | http://localhost:6333 | URL de la API REST de Qdrant |
MEM0_QDRANT_API_KEY | -- | Clave de API de Qdrant (para Qdrant Cloud) |
MEM0_QDRANT_ON_DISK | false | Almacenar vectores en disco (reduce RAM, búsqueda más lenta) |
MEM0_QDRANT_TIMEOUT | (predeterminado del cliente) | Tiempo de espera de la API REST de Qdrant en segundos (p. ej., 30). Solo configúralo si encuentras ReadTimeout durante operaciones de colección |
MEM0_COLLECTION | mem0_mcp_selfhosted | Nombre de la colección de Qdrant |
Almacén de grafos (Neo4j)
| Variable | Por defecto | Descripción |
|---|---|---|
MEM0_ENABLE_GRAPH | false | Habilitar memoria de grafos (extracción de entidades a Neo4j) |
MEM0_NEO4J_URL | bolt://127.0.0.1:7687 | Endpoint Bolt de Neo4j |
MEM0_NEO4J_USER | neo4j | Usuario de Neo4j |
MEM0_NEO4J_PASSWORD | mem0graph | Contraseña de Neo4j |
MEM0_NEO4J_DATABASE | -- | Nombre de la base de datos de Neo4j (configuraciones multi-base de datos) |
MEM0_NEO4J_BASE_LABEL | -- | Etiqueta base personalizada de Neo4j para agrupar tipos de nodos |
MEM0_GRAPH_THRESHOLD | 0.7 | Umbral de similitud de embeddings para coincidencia de nodos |
Servidor
| Variable | Por defecto | Descripción |
|---|---|---|
MEM0_TRANSPORT | stdio | Transporte: stdio, sse o streamable-http |
MEM0_HOST | 0.0.0.0 | Host para transportes SSE/HTTP |
MEM0_PORT | 8081 | Puerto para transportes SSE/HTTP |
MEM0_USER_ID | user | ID de usuario predeterminado para el alcance de memoria |
MEM0_LOG_LEVEL | INFO | Nivel de registro (DEBUG, INFO, WARNING, ERROR) |
MEM0_HISTORY_DB_PATH | -- | Ruta de SQLite para el historial de cambios de memoria |
Arquitectura
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.json
Memoria de grafos y cuota
La memoria de grafos está deshabilitada por defecto (MEM0_ENABLE_GRAPH=false) para proteger tu cuota de Claude. Cada add_memory con grafos habilitados genera 3 llamadas adicionales al LLM para extracción de entidades, generación de relaciones y resolución de conflictos.
Uso de Ollama para operaciones de grafos
Para eliminar el uso de la cuota de Claude en operaciones de grafos, usa un modelo local de Ollama:
MEM0_ENABLE_GRAPH=true
MEM0_GRAPH_LLM_PROVIDER=ollama
MEM0_GRAPH_LLM_MODEL=qwen3:14b
Qwen3:14b tiene un F1 de llamada a herramientas de 0.971 (casi igualando el 0.974 de GPT-4) y se ejecuta en ~7-8GB de VRAM con cuantización Q4_K_M.
Uso de Gemini para operaciones de grafos
El Gemini 2.5 Flash Lite de Google es la opción más económica para operaciones de grafos manteniendo una alta precisión en la extracción de entidades:
MEM0_ENABLE_GRAPH=true
MEM0_GRAPH_LLM_PROVIDER=gemini
MEM0_GRAPH_LLM_MODEL=gemini-2.5-flash-lite
GOOGLE_API_KEY=your-google-api-key
Uso de modelo dividido para mayor precisión
El proveedor gemini_split enruta las llamadas del pipeline de grafos a diferentes LLMs según la operación. La extracción de entidades (llamadas 1 y 2) va a Gemini por velocidad y costo; la detección de contradicciones (llamada 3) va a Claude por precisión.
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-6
Resultados de benchmark en 248 casos de prueba: Gemini obtiene 85.4% en extracción de entidades (vs 79.1% de Claude), mientras que Claude obtiene 100% en detección de contradicciones (vs 80% de Gemini). El modelo dividido combina lo mejor de ambos.
Modos de transporte
| Modo | Caso de uso | Configuración |
|---|---|---|
stdio (predeterminado) | Integración con Claude Code | MEM0_TRANSPORT=stdio |
sse | Clientes remotos heredados | MEM0_TRANSPORT=sse |
streamable-http | Clientes remotos modernos | MEM0_TRANSPORT=streamable-http |
Para despliegues remotos, MCP SDK >= 1.23.0 habilita la protección contra rebinding de DNS por defecto.
Desarrollo
# 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/ -v
Estructura de pruebas
tests/unit/-- Pruebas unitarias puras con dependencias simuladas (env, auth, config, matriz de configuración, concurrencia, protocolo MCP, helpers, hooks, proveedores de LLM, herramientas de grafos, enrutador de LLM, servidor)tests/contract/-- Valida suposiciones sobre los internals de mem0ai (invariante de detección de esquema, ruta de accesovector_store.client, idempotencia de registroLlmFactory)tests/integration/-- Pruebas de infraestructura en vivo (ciclo de vida de memoria, operaciones de grafos, operaciones masivas, hooks) contra Qdrant + Neo4j + Ollama reales. Marcadas con@pytest.mark.integration.
Las pruebas de contrato detectan cambios incompatibles en las actualizaciones de mem0ai antes de que lleguen a producción.
Telemetría
Toda la telemetría de mem0ai está suprimida. os.environ["MEM0_TELEMETRY"] = "false" se establece al importar el paquete, antes de que se cargue cualquier módulo mem0. No se envían eventos de PostHog.
Licencia
MIT