Smriti MCP
Smriti es un servidor del Protocolo de Contexto de Modelo (MCP) que proporciona memoria persistente basada en grafos para aplicaciones LLM. Construido sobre LadybugDB (base de datos de grafos de propiedades embebida), utiliza una recuperación multi-etapa inspirada en EcphoryRAG, combinando extracción de pistas, recorrido de grafos, similitud vectorial y asociación multi-salto, para ofrecer un recuerdo de memoria similar al humano.
Documentación
Smriti MCP
Sistema de Memoria de IA Basado en Grafos con Recuperación EcphoryRAG y Agrupamiento Leiden
Smriti es un servidor de Model Context Protocol (MCP) que proporciona memoria persistente basada en grafos para aplicaciones LLM. Soporta tres backends de base de datos — LadybugDB (integrado), Neo4j y FalkorDB — y utiliza recuperación multi-etapa inspirada en EcphoryRAG — combinando extracción de señales, recorrido de grafos, similitud vectorial y asociación multi-salto — para ofrecer un recuerdo de memoria similar al humano. Smriti utiliza el algoritmo de Leiden para la detección automática de comunidades, permitiendo una recuperación consciente de clústeres que escala más allá de miles de memorias.
Características
- Memoria Basada en Grafos — Engramas (memorias) vinculados mediante Señales y Asociaciones en un grafo de propiedades
- Recuperación EcphoryRAG — Recuerdo asociativo multi-salto con extracción de señales, similitud vectorial y puntuación compuesta
- Detección de Comunidades Leiden — Agrupamiento automático de memorias relacionadas mediante el algoritmo de Leiden con ajuste de resolución con caché inteligente, permitiendo puntuación consciente de clústeres para una recuperación eficiente a escala
- Soporte Multi-Backend — LadybugDB (integrado, sin configuración), Neo4j (base de datos de grafos empresarial) o FalkorDB (base de datos de grafos basada en Redis)
- Aislamiento Multi-Usuario — Por archivo (LadybugDB), propiedad por inquilino o por base de datos (Neo4j), o propiedad por inquilino o por grafo (FalkorDB)
- Consolidación Automática — Decaimiento exponencial, poda de memorias débiles, fortalecimiento de las de acceso frecuente y re-agrupamiento periódico de Leiden
- Copia de Seguridad Flexible — Sincronización con GitHub (git del sistema) o S3 (AWS SDK), además de noop para solo local
- Indexación HNSW Perezosa — Índices vectoriales y FTS creados bajo demanda cuando el conjunto de datos supera el umbral
- APIs Compatibles con OpenAI — Funciona con cualquier LLM compatible con OpenAI y proveedor de embeddings
- 3 Herramientas MCP —
smriti_store,smriti_recall,smriti_manage
Arquitectura
graph TD
Client["MCP Client<br/>(Cursor / Claude / Windsurf / etc.)"]
Client -->|stdio| Server
subgraph Server["Smriti MCP Server"]
direction TB
subgraph Tools["MCP Tools"]
Store["smriti_store"]
Recall["smriti_recall"]
Manage["smriti_manage"]
end
subgraph Engine["Memory Engine"]
Encoding["Encoding<br/>LLM + Embed + Link"]
Retrieval["Retrieval<br/>Cue Match + Vector + Multi-hop<br/>+ Cluster-Aware Scoring"]
Consolidation["Consolidation<br/>Decay + Prune + Leiden Clustering"]
end
subgraph DB["Graph Database"]
direction LR
Graph["(Engram)──[:EncodedBy]──▶(Cue)<br/>(Engram)──[:AssociatedWith]──▶(Engram)<br/>(Cue)──[:CoOccurs]──▶(Cue)"]
DBType["LadybugDB | Neo4j | FalkorDB"]
end
subgraph Backup["Backup Provider (optional)"]
Git["GitHub (git)"]
S3["S3 (AWS SDK)"]
Noop["Noop"]
end
Store & Recall & Manage --> Engine
Encoding & Retrieval & Consolidation --> DB
DB --> Backup
end
LLM["LLM / Embedding API<br/>(OpenAI-compatible)"]
Engine --> LLM
Pipeline de Recuperación
El modo recall predeterminado realiza recuperación multi-etapa:
- Extracción de Señales — El LLM extrae entidades y palabras clave de la consulta
- Recorrido de Grafo Basado en Señales — Sigue las aristas
EncodedBypara encontrar engramas vinculados a señales coincidentes - Búsqueda de Similitud Vectorial — Similitud de coseno contra todos los embeddings de engramas (índice HNSW cuando está disponible, con respaldo a fuerza bruta)
- Expansión Multi-Salto — Sigue las aristas
AssociatedWithpara descubrir memorias relacionadas - Puntuación Compuesta Consciente de Clústeres — Combina similitud vectorial (40%), actualidad (20%), importancia (20%) y decaimiento (20%), con penalización por profundidad de salto y penalización entre clústeres suavemente limitada (0.5x para resultados de salto fuera del clúster semilla)
- Fortalecimiento de Acceso — Los engramas recuperados ven incrementados su contador de acceso y factor de decaimiento (refuerzo)
Agrupamiento Leiden
Smriti utiliza el algoritmo de Leiden — una mejora sobre Louvain que garantiza comunidades bien conectadas — para detectar automáticamente clústeres de memorias relacionadas en el grafo.
Cómo funciona:
- Se ejecuta automáticamente durante cada ciclo de consolidación
- Construye un grafo no dirigido ponderado a partir de las aristas
AssociatedWithentre engramas - Ajusta automáticamente el parámetro de resolución mediante perfilado de comunidades en la primera ejecución
- Utiliza una caché inteligente: la resolución ajustada se reutiliza entre ejecuciones y solo se reajusta cuando el grafo crece más del 10%
- Asigna un
cluster_ida cada engrama, almacenado de forma persistente en la base de datos - Los nuevos engramas heredan el
cluster_idde su vecino más fuerte en el momento de la codificación
Cómo mejora la recuperación:
- El pipeline de recuperación determina un clúster semilla (el clúster más común entre los resultados de coincidencia directa)
- Los resultados multi-salto que cruzan a un clúster diferente reciben una penalización de puntuación de 0.5x (suavemente limitada: se penalizan, no se descartan)
- Esto mantiene la recuperación enfocada dentro del clúster temático más relevante mientras aún permite el descubrimiento entre temas
Características de rendimiento:
- Se omite correctamente en grafos pequeños (< 3 nodos o 0 aristas)
- Agrupamiento de 60 nodos: ~40ms (primera ejecución con autoajuste), ~14ms (resolución en caché)
- Por usuario: cada instancia de Engine mantiene su propia caché independiente
Pipeline de Consolidación
La consolidación se ejecuta periódicamente (por defecto: cada 3600 segundos) y realiza:
- Decaimiento Exponencial — Reduce
decay_factorsegún el tiempo transcurrido desde el último acceso - Poda de Memorias Débiles — Elimina engramas por debajo del umbral mínimo de decaimiento
- Fortalecimiento por Frecuencia — Aumenta el factor de decaimiento para memorias de acceso frecuente
- Limpieza de Señales Huérfanas — Elimina señales que ya no están vinculadas a ningún engrama
- Agrupamiento Leiden — Re-agrupa el grafo de memoria (con caché inteligente, se omite si el grafo no ha cambiado significativamente)
- Gestión de Índices — Crea índices vectoriales HNSW y FTS cuando el recuento de engramas supera el umbral (50)
Requisitos
-
Go 1.25+ — Para compilar desde el código fuente
-
Git 2.x+ — Requerido para el proveedor de copia de seguridad de GitHub (debe estar en PATH)
-
GCC/Build Tools — Requerido para CGO (backend de LadybugDB)
- macOS:
xcode-select --install - Linux:
sudo apt install build-essential - Windows: Usa Docker (recomendado) o MinGW
- macOS:
-
liblbug (biblioteca compartida de LadybugDB) — Dependencia de tiempo de ejecución para el backend de LadybugDB, descargada automáticamente por
go-ladybugdurante la compilación. Si compilas manualmente, obtén la última versión desde LadybugDB/ladybug:Plataforma Recurso Biblioteca macOS liblbug-osx-arm64.tar.gz/liblbug-osx-x86_64.tar.gzliblbug.dylibLinux liblbug-linux-{arch}.tar.gzliblbug.soWindows liblbug-windows-x86_64.zipliblbug.dllLa biblioteca compartida debe estar en la ruta de bibliotecas del sistema en tiempo de ejecución (p. ej.,
DYLD_LIBRARY_PATHen macOS,LD_LIBRARY_PATHen Linux, o junto al binario en Windows). Docker y los binarios de release incluyen esto automáticamente. -
Neo4j 5.x+ — Requerido solo cuando se usa
DB_TYPE=neo4j. Debe tener los plugins APOC y GDS para búsqueda vectorial e indexación de texto completo. -
FalkorDB — Requerido solo cuando se usa
DB_TYPE=falkordb. Se ejecuta sobre el protocolo Redis (puerto predeterminado 6379).
Inicio Rápido
1. Compilación
# Build
CGO_ENABLED=1 go build -o smriti-mcp .
# Run (minimal config)
export LLM_API_KEY=your-api-key
export ACCESSING_USER=alice
./smriti-mcp
2. Integración con Cliente MCP
Opción 1: Binario Nativo
Cursor (~/.cursor/mcp_settings.json):
{
"mcpServers": {
"smriti": {
"command": "/path/to/smriti-mcp",
"env": {
"LLM_API_KEY": "your-api-key",
"EMBEDDING_API_KEY": "your-embedding-key"
}
}
}
}
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"smriti": {
"command": "/path/to/smriti-mcp",
"args": [],
"env": {
"LLM_API_KEY": "your-api-key",
"EMBEDDING_API_KEY": "your-embedding-key"
}
}
}
}
Windsurf (~/.codeium/windsurf/mcp_config.json):
{
"mcpServers": {
"smriti": {
"command": "/path/to/smriti-mcp",
"env": {
"LLM_API_KEY": "your-api-key",
"EMBEDDING_API_KEY": "your-embedding-key"
}
}
}
}
Opción 2: Go Run
Ejecuta directamente sin instalar — similar a npx para Node.js:
{
"mcpServers": {
"smriti": {
"command": "go",
"args": ["run", "github.com/tejzpr/smriti-mcp@latest"],
"env": {
"LLM_API_KEY": "your-api-key",
"EMBEDDING_API_KEY": "your-embedding-key"
}
}
}
}
Opción 3: Contenedor Docker
Modo simple (usuario único):
{
"mcpServers": {
"smriti": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/yourname/.smriti:/home/smriti/.smriti",
"-e", "LLM_API_KEY=your-api-key",
"-e", "EMBEDDING_API_KEY=your-embedding-key",
"tejzpr/smriti-mcp"
]
}
}
}
Modo multi-usuario:
{
"mcpServers": {
"smriti": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/yourname/.smriti:/home/smriti/.smriti",
"-e", "LLM_API_KEY=your-api-key",
"-e", "EMBEDDING_API_KEY=your-embedding-key",
"-e", "ACCESSING_USER=yourname",
"tejzpr/smriti-mcp"
]
}
}
}
Nota:
- Reemplaza
/Users/yournamecon la ruta real de tu directorio de inicio- Los clientes MCP no expanden
$HOMEni~en las configuraciones JSON — usa rutas absolutas- El montaje de volumen
.smritipersiste tu base de datos de memoria- El contenedor se ejecuta como usuario no root
smriti
Compilar localmente (opcional):
docker build -t smriti-mcp .
Luego usa smriti-mcp en lugar de tejzpr/smriti-mcp en tu configuración.
Opción 4: Binario de Release de GitHub
Descarga binarios precompilados desde la página de Releases. Los binarios están disponibles para:
| Plataforma | Arquitectura | CGO |
|---|---|---|
| Linux | amd64 | Habilitado (nativo) |
| macOS | arm64 (Apple Silicon) | Habilitado (nativo) |
| Windows | amd64 | Habilitado (nativo) |
Cada release incluye un checksums-sha256.txt para verificación.
Variables de Entorno
Núcleo
| Variable | Predeterminado | Descripción |
|---|---|---|
ACCESSING_USER | Nombre de usuario del SO | Identificador de usuario (usado para aislamiento de BD) |
STORAGE_LOCATION | ~/.smriti | Directorio raíz de almacenamiento (solo LadybugDB) |
DB_TYPE | ladybug | Backend de base de datos: ladybug, neo4j o falkordb |
LLM
| Variable | Predeterminado | Descripción |
|---|---|---|
LLM_BASE_URL | https://api.openai.com/v1 | Endpoint de API LLM (compatible con OpenAI) |
LLM_API_KEY | (requerida) | Clave de API LLM |
LLM_MODEL | gpt-4o-mini | Nombre del modelo LLM |
Embedding
| Variable | Predeterminado | Descripción |
|---|---|---|
EMBEDDING_BASE_URL | https://api.openai.com/v1 | Endpoint de API de embeddings |
EMBEDDING_API_KEY | (usa LLM_API_KEY como respaldo) | Clave de API de embeddings |
EMBEDDING_MODEL | text-embedding-3-small | Nombre del modelo de embeddings |
EMBEDDING_DIMS | 1536 | Dimensiones del vector de embeddings |
Copia de Seguridad
| Variable | Predeterminado | Descripción |
|---|---|---|
BACKUP_TYPE | none | none, github o s3 |
BACKUP_SYNC_INTERVAL | 60 | Segundos entre sincronizaciones de copia de seguridad (0 = deshabilitado) |
GIT_BASE_URL | (vacío) | URL base remota de Git (requerida si github) |
S3_ENDPOINT | (vacío) | Endpoint S3 (para proveedores que no son AWS) |
S3_REGION | (vacío) | Región S3 (requerida si s3) |
S3_ACCESS_KEY | (vacío) | Clave de acceso S3 (requerida si s3) |
S3_SECRET_KEY | (vacío) | Clave secreta S3 (requerida si s3) |
Neo4j (cuando DB_TYPE=neo4j)
| Variable | Predeterminado | Descripción |
|---|---|---|
NEO4J_URI | (requerida) | URI Bolt (p. ej. bolt://localhost:7687) |
NEO4J_USERNAME | (requerido) | Nombre de usuario de Neo4j |
NEO4J_PASSWORD | (requerida) | Contraseña de Neo4j |
NEO4J_DATABASE | neo4j | Nombre de la base de datos (anulado por el nombre de usuario en modo de aislamiento database) |
NEO4J_ISOLATION | tenant | tenant (basado en propiedades, Community Edition) o database (por BD, Enterprise Edition) |
FalkorDB (cuando DB_TYPE=falkordb)
| Variable | Predeterminado | Descripción |
|---|---|---|
FALKOR_ADDR | localhost:6379 | Dirección Redis de FalkorDB |
FALKOR_PASSWORD | (vacío) | Contraseña de FalkorDB (si la autenticación está habilitada) |
FALKOR_GRAPH | smriti | Nombre del grafo (anulado por {user}_smriti en modo de aislamiento graph) |
FALKOR_ISOLATION | tenant | tenant (basado en propiedades) o graph (aislamiento por grafo) |
Consolidación
| Variable | Predeterminado | Descripción |
|---|---|---|
CONSOLIDATION_INTERVAL | 3600 | Segundos entre ejecuciones de consolidación (0 = deshabilitado) |
Herramientas MCP
smriti_store
"Recuerda esto" — Almacena una nueva memoria. El contenido se analiza automáticamente por el LLM, se incrusta y se integra en el grafo de memoria. Los nuevos engramas heredan el cluster_id de su vecino existente más similar.
{
"content": "Kubernetes uses etcd as its backing store for all cluster data",
"importance": 0.8,
"tags": "kubernetes,etcd,infrastructure",
"source": "meeting-notes"
}
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
content | string | sí | Contenido de la memoria |
importance | number | no | Prioridad 0.0–1.0 (predeterminado: 0.5) |
tags | string | no | Etiquetas separadas por comas |
source | string | no | Etiqueta de fuente/origen |
smriti_recall
"¿Qué sé sobre X?" — Recupera memorias utilizando recuperación EcphoryRAG multi-etapa con puntuación consciente de clústeres.
{
"query": "container orchestration tools",
"limit": 5,
"mode": "recall"
}
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
query | string | no | Consulta en lenguaje natural (omitir para modo lista) |
limit | number | no | Máximo de resultados (predeterminado: 5) |
mode | string | no | recall (multi-salto profundo), search (solo vectorial rápido) o list (explorar) |
memory_type | string | no | Filtro: episodic, semantic, procedural |
| Modos explicados: |
recall(predeterminado) — Pipeline completo: extracción de señales → recorrido del grafo → búsqueda vectorial → multi-salto → puntuación compuesta consciente de clústeressearch— Similitud coseno solo vectorial. Más rápido pero menos profundo.list— Sin búsqueda. Devuelve recuerdos recientes ordenados por tiempo de último acceso.
smriti_manage
"Olvida esto / sincroniza ahora" — Operaciones administrativas.
{
"action": "forget",
"memory_id": "abc-123-def"
}
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
action | string | sí | forget (eliminar memoria) o sync (enviar copia de seguridad) |
memory_id | string | si es forget | ID del engrama a eliminar |
Esquema del Grafo
Smriti almacena memorias en un grafo de propiedades con la siguiente estructura:
Node Tables:
Engram — id, content, summary, memory_type, importance, access_count,
created_at, last_accessed_at, decay_factor, embedding, source,
tags, cluster_id
Cue — id, name, cue_type, embedding
Relationship Tables:
EncodedBy — (Engram) → (Cue)
AssociatedWith — (Engram) → (Engram) [strength, relation_type, created_at]
CoOccurs — (Cue) → (Cue) [strength]
El campo cluster_id en los nodos Engram es gestionado por el algoritmo de Leiden. Un valor de -1 indica que el engrama aún no ha sido asignado a un clúster (por ejemplo, el grafo es demasiado pequeño, o el engrama no tiene asociaciones).
Almacenamiento y Aislamiento
Smriti soporta tres motores de base de datos con diferentes modelos de almacenamiento y aislamiento:
LadybugDB (predeterminado)
Cada usuario obtiene un archivo de base de datos embebida aislado:
~/.smriti/
└── {username}/
└── memory.lbug # LadybugDB property graph database
La variable de entorno STORAGE_LOCATION controla la raíz. La variable de entorno ACCESSING_USER selecciona la base de datos del usuario a abrir. Los proveedores de copias de seguridad sincronizan el directorio del usuario con almacenamiento remoto.
Neo4j
Dos modos de aislamiento controlados por NEO4J_ISOLATION:
tenant(predeterminado) — Todos los usuarios comparten una base de datos. Cada nodo obtiene una propiedadusery todas las consultas filtran por ella. Funciona en Neo4j Community Edition.database— Cada usuario obtiene una base de datos Neo4j separada. Requiere Neo4j Enterprise Edition.
FalkorDB
Dos modos de aislamiento controlados por FALKOR_ISOLATION:
tenant(predeterminado) — Todos los usuarios comparten un grafo. Cada nodo obtiene una propiedadusery todas las consultas filtran por ella.graph— Cada usuario obtiene un grafo separado (llamado{user}_smriti).
Las migraciones de esquema (por ejemplo, agregar cluster_id a bases de datos existentes) se ejecutan automáticamente al inicio.
Estructura del Proyecto
smriti-mcp/
├── main.go # Entry point, server setup, signal handling
├── config/ # Environment variable parsing
├── llm/ # OpenAI-compatible HTTP client (LLM + embeddings)
├── db/ # Database backends (LadybugDB, Neo4j, FalkorDB), schema, indexes, migrations
├── memory/
│ ├── engine.go # Engine struct, consolidation loop
│ ├── types.go # Engram, Cue, Association, SearchResult structs
│ ├── encoding.go # Store pipeline: LLM extraction → embed → link → cluster inherit
│ ├── retrieval.go # Recall pipeline: cue search → vector → multi-hop → cluster scoring
│ ├── search.go # Search modes: list, vector-only, FTS, hybrid
│ ├── consolidation.go # Decay, prune, strengthen, orphan cleanup
│ └── leiden.go # Leiden clustering: graph build, auto-tune, smart cache, batch write
├── backup/ # Backup providers: noop, github (git), s3 (AWS SDK)
├── tools/ # MCP tool definitions: store, recall, manage
└── testutil/ # Shared test helpers
Pruebas
# Run unit tests
CGO_ENABLED=1 go test ./...
# Verbose with all output
CGO_ENABLED=1 go test -v ./...
# Specific package
CGO_ENABLED=1 go test -v ./memory/...
CGO_ENABLED=1 go test -v ./tools/...
# Leiden clustering tests only
CGO_ENABLED=1 go test -v -run "TestRunLeiden|TestNeedsRetune|TestDetermineSeedCluster" ./memory/
Pruebas E2E / Integración
Las pruebas E2E requieren servicios reales de LLM/embeddings y están restringidas detrás de la etiqueta de compilación integration:
# LadybugDB E2E (no external DB required)
CGO_ENABLED=1 go test -tags integration -v -run "TestE2E_LadybugDB" ./memory/
# Neo4j E2E (requires running Neo4j instance)
NEO4J_URI="bolt://localhost:7687" NEO4J_USERNAME="neo4j" NEO4J_PASSWORD="yourpass" \
CGO_ENABLED=1 go test -tags integration -v -run "TestE2E_Neo4j" ./memory/
# FalkorDB E2E (requires running FalkorDB instance)
FALKOR_ADDR="localhost:6379" \
CGO_ENABLED=1 go test -tags integration -v -run "TestE2E_FalkorDB" ./memory/
# All E2E tests
CGO_ENABLED=1 go test -tags integration -v -run "TestE2E_" ./memory/
Todas las pruebas E2E requieren las variables de entorno LLM_BASE_URL, LLM_API_KEY, LLM_MODEL, EMBEDDING_BASE_URL, EMBEDDING_MODEL y EMBEDDING_API_KEY.
Contribuciones
¡Las contribuciones son bienvenidas! Por favor, asegúrate de:
- Todas las pruebas pasen (
CGO_ENABLED=1 go test ./...) - El código esté correctamente formateado (
go fmt ./...) - El código nuevo incluya el encabezado de licencia SPDX
Consulta CONTRIBUTORS.md para la lista de contribuyentes.
Licencia
Este proyecto está licenciado bajo la GNU Affero General Public License v3.0 (AGPL-3.0) desde la versión v1.0.7 en adelante.
Las versiones anteriores a v1.0.7 están licenciadas bajo la Mozilla Public License 2.0.