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 Logo

Smriti MCP

Go Version License: AGPL v3.0 MCP Docker Hub CodeQL

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:

  1. Extração de Pistas — O LLM extrai entidades e palavras-chave da consulta
  2. Travessia de Grafo Baseada em Pistas — Segue arestas EncodedBy para encontrar engramas vinculados a pistas correspondentes
  3. Busca por Similaridade Vetorial — Similaridade de cosseno contra todas as incorporações de engramas (índice HNSW quando disponível, fallback para força bruta)
  4. Expansão Multi-Salto — Segue arestas AssociatedWith para descobrir memórias relacionadas
  5. 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)
  6. 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 AssociatedWith entre 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_id a cada engrama, armazenado persistentemente no banco de dados
  • Novos engramas herdam o cluster_id de 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:

  1. Decaimento Exponencial — Reduz decay_factor com base no tempo desde o último acesso
  2. Poda de Memórias Fracas — Remove engramas abaixo do limite mínimo de decaimento
  3. Fortalecimento por Frequência — Aumenta o fator de decaimento para memórias acessadas com frequência
  4. Limpeza de Pistas Órfãs — Remove pistas não mais vinculadas a nenhum engrama
  5. Agrupamento Leiden — Re-agrupa o grafo de memória (cache inteligente, ignora se o grafo não mudou significativamente)
  6. 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
  • liblbug (biblioteca compartilhada LadybugDB) — Dependência de tempo de execução para o backend LadybugDB, baixada automaticamente por go-ladybug durante o build. Se compilar manualmente, obtenha a versão mais recente de LadybugDB/ladybug:

    PlataformaAssetBiblioteca
    macOSliblbug-osx-arm64.tar.gz / liblbug-osx-x86_64.tar.gzliblbug.dylib
    Linuxliblbug-linux-{arch}.tar.gzliblbug.so
    Windowsliblbug-windows-x86_64.zipliblbug.dll

    A biblioteca compartilhada deve estar no caminho de bibliotecas do sistema em tempo de execução (por exemplo, DYLD_LIBRARY_PATH no macOS, LD_LIBRARY_PATH no 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/yourname pelo caminho real do seu diretório inicial
  • Clientes MCP não expandem $HOME ou ~ em configurações JSON — use caminhos absolutos
  • O volume montado .smriti persiste 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:

PlataformaArquiteturaCGO
Linuxamd64Habilitado (nativo)
macOSarm64 (Apple Silicon)Habilitado (nativo)
Windowsamd64Habilitado (nativo)

Cada release inclui um checksums-sha256.txt para verificação.

Variáveis de Ambiente

Núcleo

VariávelPadrãoDescrição
ACCESSING_USERNome de usuário do SOIdentificador do usuário (usado para isolamento do banco de dados)
STORAGE_LOCATION~/.smritiDiretório raiz de armazenamento (somente LadybugDB)
DB_TYPEladybugBackend do banco de dados: ladybug, neo4j ou falkordb

LLM

VariávelPadrãoDescrição
LLM_BASE_URLhttps://api.openai.com/v1Endpoint da API LLM (compatível com OpenAI)
LLM_API_KEY(obrigatório)Chave da API LLM
LLM_MODELgpt-4o-miniNome do modelo LLM

Incorporação

VariávelPadrãoDescrição
EMBEDDING_BASE_URLhttps://api.openai.com/v1Endpoint da API de incorporação
EMBEDDING_API_KEY(usa fallback para LLM_API_KEY)Chave da API de incorporação
EMBEDDING_MODELtext-embedding-3-smallNome do modelo de incorporação
EMBEDDING_DIMS1536Dimensões do vetor de incorporação

Backup

VariávelPadrãoDescrição
BACKUP_TYPEnonenone, github ou s3
BACKUP_SYNC_INTERVAL60Segundos 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ávelPadrãoDescriçã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_DATABASEneo4jNome do banco de dados (substituído pelo nome de usuário no modo de isolamento database)
NEO4J_ISOLATIONtenanttenant (baseado em propriedade, Community Edition) ou database (por banco de dados, Enterprise Edition)

FalkorDB (quando DB_TYPE=falkordb)

VariávelPadrãoDescrição
FALKOR_ADDRlocalhost:6379Endereço Redis do FalkorDB
FALKOR_PASSWORD(vazio)Senha do FalkorDB (se autenticação habilitada)
FALKOR_GRAPHsmritiNome do grafo (substituído por {user}_smriti no modo de isolamento graph)
FALKOR_ISOLATIONtenanttenant (baseado em propriedade) ou graph (isolamento por grafo)

Consolidação

VariávelPadrãoDescrição
CONSOLIDATION_INTERVAL3600Segundos 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âmetroTipoObrigatórioDescrição
contentstringsimConteúdo da memória
importancenumbernãoPrioridade 0.0–1.0 (padrão: 0.5)
tagsstringnãoTags separadas por vírgula
sourcestringnãoRó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âmetroTipoObrigatórioDescrição
querystringnãoConsulta em linguagem natural (omitir para modo de lista)
limitnumbernãoMáximo de resultados (padrão: 5)
modestringnãorecall (multi-salto profundo), search (somente vetorial rápido) ou list (navegação)
memory_typestringnãoFiltro: 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 clusters
  • search — 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âmetroTipoObrigatórioDescrição
actionstringsimforget (excluir memória) ou sync (enviar backup)
memory_idstringse esquecerID 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 propriedade user e 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 propriedade user e 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.