Smriti MCP
Smriti é um servidor Model Context Protocol (MCP) que fornece memória persistente baseada em grafos para aplicações LLM. Construído sobre LadybugDB (banco de dados de grafos de propriedades embutido), utiliza recuperação multiestágio inspirada em EcphoryRAG - combinando extração de pistas, travessia de grafos, similaridade vetorial e associação multi-hop - para proporcionar uma recuperação de memória semelhante à humana.
Documentação
Smriti MCP
Sistema de Memória de IA Baseado em Grafo com Recuperação EcphoryRAG e Agrupamento Leiden
Smriti é um servidor MCP (Model Context Protocol) que fornece memória persistente baseada em grafo para aplicações de LLM. Ele suporta três backends de banco de dados — LadybugDB (embutido), Neo4j e FalkorDB — e usa recuperação multi-estágio inspirada em EcphoryRAG — combinando extração de pistas, travessia de grafo, similaridade vetorial e associação multi-salto — para proporcionar recall de memória semelhante ao humano. Smriti usa o algoritmo Leiden para detecção automática de comunidades, permitindo recuperação ciente de agrupamentos que escala além de milhares de memórias.
Recursos
- Memória Baseada em Grafo — Engramas (memórias) vinculados por meio de Pistas e Associações em um grafo de propriedades
- Recuperação EcphoryRAG — Recall associativo multi-salto com extração de pistas, similaridade vetorial e pontuação composta
- Detecção de Comunidades Leiden — Agrupamento automático de memórias relacionadas usando o algoritmo Leiden com ajuste de resolução com cache inteligente, permitindo pontuação ciente de agrupamentos para recuperação eficiente em escala
- Suporte Multi-Backend — LadybugDB (embutido, zero configuração), Neo4j (banco de dados de grafo empresarial) ou FalkorDB (banco de dados de grafo baseado em Redis)
- Isolamento Multi-Usuário — Por arquivo (LadybugDB), por propriedade de locatário ou por banco de dados (Neo4j), ou por propriedade de locatário ou por grafo (FalkorDB)
- Consolidação Automática — Decaimento exponencial, poda de memórias fracas, fortalecimento das acessadas com frequência e re-agrupamento periódico com Leiden
- Backup Flexível — Sincronização com GitHub (git do sistema) ou S3 (AWS SDK), além de noop para somente local
- Indexação HNSW Preguiçosa — Índices vetoriais e FTS criados sob demanda quando o conjunto de dados excede o limite
- APIs Compatíveis com OpenAI — Funciona com qualquer provedor de LLM e incorporação compatível com OpenAI
- 3 Ferramentas MCP —
smriti_store,smriti_recall,smriti_manage
Arquitetura
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 Recall
O modo padrão recall executa recuperação multi-estágio:
- Extração de Pistas — O LLM extrai entidades e palavras-chave da consulta
- Travessia de Grafo Baseada em Pistas — Segue arestas
EncodedBypara encontrar engramas vinculados a pistas correspondentes - Busca por Similaridade Vetorial — Similaridade de cosseno contra todas as incorporações de engramas (índice HNSW quando disponível, fallback para força bruta)
- Expansão Multi-Salto — Segue arestas
AssociatedWithpara descobrir memórias relacionadas - Pontuação Composta Ciente de Agrupamento — Combina similaridade vetorial (40%), recência (20%), importância (20%) e decaimento (20%), com penalidade de profundidade de salto e penalidade entre agrupamentos com limite suave (0,5x para resultados de salto fora do agrupamento inicial)
- Fortalecimento de Acesso — Engramas recuperados têm sua contagem de acesso e fator de decaimento aumentados (reforço)
Agrupamento Leiden
Smriti usa o algoritmo Leiden — uma melhoria em relação ao Louvain que garante comunidades bem conectadas — para detectar automaticamente agrupamentos de memórias relacionadas no grafo.
Como funciona:
- Executa automaticamente durante cada ciclo de consolidação
- Constrói um grafo não direcionado ponderado a partir de arestas
AssociatedWithentre engramas - Ajusta automaticamente o parâmetro de resolução usando perfil de comunidade na primeira execução
- Usa um cache inteligente: a resolução ajustada é reutilizada entre execuções e só é reajustada quando o grafo cresce mais de 10%
- Atribui um
cluster_ida cada engrama, armazenado persistentemente no banco de dados - Novos engramas herdam o
cluster_idde seu vizinho mais forte no momento da codificação
Como melhora a recuperação:
- O pipeline de recall determina um agrupamento inicial (agrupamento mais comum entre resultados de correspondência direta)
- Resultados multi-salto que cruzam para um agrupamento diferente recebem uma penalidade de pontuação de 0,5x (limite suave: são penalizados, não descartados)
- Isso mantém a recuperação focada no agrupamento de tópico mais relevante, enquanto ainda permite descoberta entre tópicos
Características de desempenho:
- Ignora graciosamente grafos pequenos (< 3 nós ou 0 arestas)
- Agrupamento de 60 nós: ~40ms (primeira execução com ajuste automático), ~14ms (resolução em cache)
- Por usuário: cada instância de Engine mantém seu próprio cache independente
Pipeline de Consolidação
A consolidação é executada periodicamente (padrão: a cada 3600 segundos) e realiza:
- Decaimento Exponencial — Reduz
decay_factorcom base no tempo desde o último acesso - Poda de Memórias Fracas — Remove engramas abaixo do limite mínimo de decaimento
- Fortalecimento por Frequência — Aumenta o fator de decaimento para memórias acessadas com frequência
- Limpeza de Pistas Órfãs — Remove pistas não mais vinculadas a nenhum engrama
- Agrupamento Leiden — Re-agrupa o grafo de memória (cache inteligente, ignora se o grafo não mudou significativamente)
- Gerenciamento de Índices — Cria índices vetoriais HNSW e FTS quando a contagem de engramas excede o limite (50)
Requisitos
-
Go 1.25+ — Para compilar a partir do código-fonte
-
Git 2.x+ — Necessário para o provedor de backup GitHub (deve estar no PATH)
-
GCC/Ferramentas de Build — Necessário para CGO (backend LadybugDB)
- macOS:
xcode-select --install - Linux:
sudo apt install build-essential - Windows: Use Docker (recomendado) ou MinGW
- macOS:
-
liblbug (biblioteca compartilhada LadybugDB) — Dependência de tempo de execução para o backend LadybugDB, baixada automaticamente por
go-ladybugdurante o build. Se compilar manualmente, obtenha a versão mais recente de LadybugDB/ladybug:Plataforma Asset 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.dllA biblioteca compartilhada deve estar no caminho de bibliotecas do sistema em tempo de execução (por exemplo,
DYLD_LIBRARY_PATHno macOS,LD_LIBRARY_PATHno Linux, ou junto ao binário no Windows). Docker e binários de release incluem isso automaticamente. -
Neo4j 5.x+ — Necessário apenas ao usar
DB_TYPE=neo4j. Deve ter os plugins APOC e GDS para busca vetorial e indexação de texto completo. -
FalkorDB — Necessário apenas ao usar
DB_TYPE=falkordb. Executa no protocolo Redis (porta padrão 6379).
Início Rápido
1. Build
# 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. Integração com Cliente MCP
Opção 1: Binário 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"
}
}
}
}
Opção 2: Go Run
Execute diretamente sem instalar — semelhante ao 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"
}
}
}
}
Opção 3: Contêiner Docker
Modo simples (usuário ú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-usuário:
{
"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:
- Substitua
/Users/yournamepelo caminho real do seu diretório inicial- Clientes MCP não expandem
$HOMEou~em configurações JSON — use caminhos absolutos- O volume montado
.smritipersiste seu banco de dados de memória- O contêiner executa como usuário não root
smriti
Build local (opcional):
docker build -t smriti-mcp .
Em seguida, use smriti-mcp em vez de tejzpr/smriti-mcp na sua configuração.
Opção 4: Binário de Release do GitHub
Baixe binários pré-compilados da página Releases. Os binários estão disponíveis para:
| Plataforma | Arquitetura | CGO |
|---|---|---|
| Linux | amd64 | Habilitado (nativo) |
| macOS | arm64 (Apple Silicon) | Habilitado (nativo) |
| Windows | amd64 | Habilitado (nativo) |
Cada release inclui um checksums-sha256.txt para verificação.
Variáveis de Ambiente
Núcleo
| Variável | Padrão | Descrição |
|---|---|---|
ACCESSING_USER | Nome de usuário do SO | Identificador do usuário (usado para isolamento do banco de dados) |
STORAGE_LOCATION | ~/.smriti | Diretório raiz de armazenamento (somente LadybugDB) |
DB_TYPE | ladybug | Backend do banco de dados: ladybug, neo4j ou falkordb |
LLM
| Variável | Padrão | Descrição |
|---|---|---|
LLM_BASE_URL | https://api.openai.com/v1 | Endpoint da API LLM (compatível com OpenAI) |
LLM_API_KEY | (obrigatório) | Chave da API LLM |
LLM_MODEL | gpt-4o-mini | Nome do modelo LLM |
Incorporação
| Variável | Padrão | Descrição |
|---|---|---|
EMBEDDING_BASE_URL | https://api.openai.com/v1 | Endpoint da API de incorporação |
EMBEDDING_API_KEY | (usa fallback para LLM_API_KEY) | Chave da API de incorporação |
EMBEDDING_MODEL | text-embedding-3-small | Nome do modelo de incorporação |
EMBEDDING_DIMS | 1536 | Dimensões do vetor de incorporação |
Backup
| Variável | Padrão | Descrição |
|---|---|---|
BACKUP_TYPE | none | none, github ou s3 |
BACKUP_SYNC_INTERVAL | 60 | Segundos entre sincronizações de backup (0 = desabilitado) |
GIT_BASE_URL | (vazio) | URL base do repositório Git (obrigatório se github) |
S3_ENDPOINT | (vazio) | Endpoint S3 (para provedores não AWS) |
S3_REGION | (vazio) | Região S3 (obrigatória se s3) |
S3_ACCESS_KEY | (vazio) | Chave de acesso S3 (obrigatória se s3) |
S3_SECRET_KEY | (vazio) | Chave secreta S3 (obrigatória se s3) |
Neo4j (quando DB_TYPE=neo4j)
| Variável | Padrão | Descrição |
|---|---|---|
NEO4J_URI | (obrigatório) | URI Bolt (por exemplo, bolt://localhost:7687) |
NEO4J_USERNAME | (obrigatório) | Nome de usuário do Neo4j |
NEO4J_PASSWORD | (obrigatório) | Senha do Neo4j |
NEO4J_DATABASE | neo4j | Nome do banco de dados (substituído pelo nome de usuário no modo de isolamento database) |
NEO4J_ISOLATION | tenant | tenant (baseado em propriedade, Community Edition) ou database (por banco de dados, Enterprise Edition) |
FalkorDB (quando DB_TYPE=falkordb)
| Variável | Padrão | Descrição |
|---|---|---|
FALKOR_ADDR | localhost:6379 | Endereço Redis do FalkorDB |
FALKOR_PASSWORD | (vazio) | Senha do FalkorDB (se autenticação habilitada) |
FALKOR_GRAPH | smriti | Nome do grafo (substituído por {user}_smriti no modo de isolamento graph) |
FALKOR_ISOLATION | tenant | tenant (baseado em propriedade) ou graph (isolamento por grafo) |
Consolidação
| Variável | Padrão | Descrição |
|---|---|---|
CONSOLIDATION_INTERVAL | 3600 | Segundos entre execuções de consolidação (0 = desabilitado) |
Ferramentas MCP
smriti_store
"Lembre-se disso" — Armazena uma nova memória. O conteúdo é automaticamente analisado pelo LLM, incorporado e tecido no grafo de memória. Novos engramas herdam o cluster_id de seu vizinho existente mais semelhante.
{
"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 | Obrigatório | Descrição |
|---|---|---|---|
content | string | sim | Conteúdo da memória |
importance | number | não | Prioridade 0.0–1.0 (padrão: 0.5) |
tags | string | não | Tags separadas por vírgula |
source | string | não | Rótulo de origem/fonte |
smriti_recall
"O que eu sei sobre X?" — Recupera memórias usando recuperação EcphoryRAG multi-estágio com pontuação ciente de agrupamento.
{
"query": "container orchestration tools",
"limit": 5,
"mode": "recall"
}
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
query | string | não | Consulta em linguagem natural (omitir para modo de lista) |
limit | number | não | Máximo de resultados (padrão: 5) |
mode | string | não | recall (multi-salto profundo), search (somente vetorial rápido) ou list (navegação) |
memory_type | string | não | Filtro: episodic, semantic, procedural |
| Modos explicados: |
recall(padrão) — Pipeline completo: extração de pistas → travessia de grafo → busca vetorial → multi-salto → pontuação composta ciente de clusterssearch— Similaridade de cosseno apenas vetorial. Mais rápida, porém mais superficial.list— Sem busca. Retorna memórias recentes ordenadas por tempo do último acesso.
smriti_manage
"Esqueça isto / sincronize agora" — Operações administrativas.
{
"action": "forget",
"memory_id": "abc-123-def"
}
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
action | string | sim | forget (excluir memória) ou sync (enviar backup) |
memory_id | string | se esquecer | ID do engrama a excluir |
Esquema do Grafo
O Smriti armazena memórias em um grafo de propriedades com a seguinte estrutura:
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]
O campo cluster_id nos nós de Engrama é gerenciado pelo algoritmo de Leiden. Um valor de -1 indica que o engrama ainda não foi atribuído a um cluster (por exemplo, o grafo é muito pequeno ou o engrama não possui associações).
Armazenamento e Isolamento
O Smriti suporta três backends de banco de dados com diferentes modelos de armazenamento e isolamento:
LadybugDB (padrão)
Cada usuário recebe um arquivo de banco de dados embutido isolado:
~/.smriti/
└── {username}/
└── memory.lbug # LadybugDB property graph database
A variável de ambiente STORAGE_LOCATION controla a raiz. A variável de ambiente ACCESSING_USER seleciona qual banco de dados do usuário abrir. Os provedores de backup sincronizam o diretório do usuário com o armazenamento remoto.
Neo4j
Dois modos de isolamento controlados por NEO4J_ISOLATION:
tenant(padrão) — Todos os usuários compartilham um único banco de dados. Cada nó recebe uma propriedadeusere todas as consultas filtram por ela. Funciona na Neo4j Community Edition.database— Cada usuário recebe um banco de dados Neo4j separado. Requer Neo4j Enterprise Edition.
FalkorDB
Dois modos de isolamento controlados por FALKOR_ISOLATION:
tenant(padrão) — Todos os usuários compartilham um único grafo. Cada nó recebe uma propriedadeusere todas as consultas filtram por ela.graph— Cada usuário recebe um grafo separado (nomeado{user}_smriti).
Migrações de esquema (por exemplo, adicionar cluster_id a bancos de dados existentes) são executadas automaticamente na inicialização.
Estrutura do Projeto
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
Testes
# 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/
Testes E2E / Integração
Os testes E2E exigem serviços reais de LLM/embedding e são controlados pela tag de build 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/
Todos os testes E2E exigem as variáveis de ambiente LLM_BASE_URL, LLM_API_KEY, LLM_MODEL, EMBEDDING_BASE_URL, EMBEDDING_MODEL e EMBEDDING_API_KEY.
Contribuindo
Contribuições são bem-vindas! Por favor, garanta que:
- Todos os testes passem (
CGO_ENABLED=1 go test ./...) - O código esteja devidamente formatado (
go fmt ./...) - Novo código inclua o cabeçalho de licença SPDX
Veja CONTRIBUTORS.md para a lista de contribuidores.
Licença
Este projeto é licenciado sob a GNU Affero General Public License v3.0 (AGPL-3.0) a partir da v1.0.7.
Versões anteriores à v1.0.7 são licenciadas sob a Mozilla Public License 2.0.