mnemon-mcp
Memória persistente em camadas para agentes de IA — modelo de 4 camadas, busca FTS5, versionamento de fatos, stemming EN+RU. Local-first, zero-cloud, arquivo SQLite único.
Documentação
mnemon-mcp
Memória persistente em camadas para agentes de IA. Local-first. Zero-nuvem. Um único arquivo SQLite.
Página Inicial · npm · GitHub
Seu agente de IA esquece tudo após cada sessão. O Mnemon resolve isso.
Ele dá a qualquer cliente compatível com MCP — OpenClaw, Claude Code, Cursor, Windsurf, ou o seu próprio — uma memória estruturada de longo prazo apoiada por um único banco de dados SQLite na sua máquina. Sem chaves de API, sem nuvem, sem telemetria. Apenas npm install e seu agente se lembra.
Por que Memória em Camadas?
Armazenamentos simples de chave-valor tratam "o que aconteceu ontem" da mesma forma que "nunca faça commit sem testes". Isso está errado — diferentes tipos de conhecimento têm diferentes tempos de vida e padrões de acesso.
O Mnemon organiza memórias em quatro camadas:
| Camada | O que armazena | Como é acessada | Tempo de vida |
|---|---|---|---|
| Episódica | Eventos, sessões, entradas de diário | Por data ou período | Decai (meia-vida de 30 dias) |
| Semântica | Fatos, preferências, relacionamentos | Por tópico ou entidade | Estável |
| Procedural | Regras, fluxos de trabalho, convenções | Carregada na inicialização | Raramente muda |
| Recurso | Material de referência, notas de livros | Sob demanda | Decai lentamente (90 dias) |
Uma entrada de diário da última terça-feira e uma regra de codificação que nunca muda vivem em camadas diferentes — porque deveriam.
Qualidade da Recuperação
A recuperação é medida contra um conjunto dourado de 50 casos em um corpus bilíngue (RU/EN) real de 797 memórias, através do servidor MCP real — não uma reimplementação. Números atuais (metodologia e histórico):
| Métrica | Somente FTS | Somente vetor | Híbrido (RRF) |
|---|---|---|---|
| Pontuação composta | 88.9 | 89.2 | 91.7 |
| Recall@5 | 0.907 | 0.898 | 0.919 |
| MRR | 0.817 | 0.832 | 0.878 |
| nDCG@5 | 0.816 | 0.828 | 0.869 |
| Precisão negativa | 1.000 | 1.000 | 1.000 |
O híbrido supera ambas as pernas individualmente, o que é todo o argumento para fundi-las: a busca lexical tem o melhor recall bruto, a busca vetorial tem o melhor ranking, e o RRF mantém ambos em vez de calculá-los como média.
O documento de avaliação também rastreia as falhas — desvio de pontuação sob crescimento do corpus, o bug de ponderação de campo BM25 que a avaliação capturou, os dois casos em que a fusão ainda perde para a busca lexical pura, e o que o conjunto dourado não cobre. Números que você não pode auditar são marketing; leia como estes são produzidos.
Arquitetura
flowchart LR
C["MCP client<br/>Claude Code · Cursor · …"] -- "stdio / HTTP" --> T["10 tools · 4 resources · 3 prompts"]
T --> R["retrieval pipeline<br/>FTS5 · vector · RRF fusion"]
T --> M["memories + supersede chains"]
I["KB import pipeline<br/>markdown → memories"] --> M
M -- triggers --> F["FTS5 index (stemmed EN+RU)"]
R --> F
R --> V["sqlite-vec (optional, BYOK)"]
Um único arquivo SQLite armazena memórias, o índice FTS5 e o índice vetorial opcional. Escritas passam por transações que mantêm o invariante da cadeia de substituição; leituras executam o pipeline de recuperação em etapas descrito em Busca.
O quadro completo — limites de módulos, caminhos de escrita/leitura, invariantes e limitações conhecidas — está em docs/ARCHITECTURE.md. Decisões de design são registradas como ADRs: núcleo SQLite+FTS5, recuperação híbrida RRF, driver síncrono, modelo de memória em camadas.
Início Rápido
Instalação
npm install -g mnemon-mcp
Ou a partir do código-fonte:
git clone https://github.com/nikitacometa/mnemon-memory-mcp.git
cd mnemon-memory-mcp && npm install && npm run build
Configure Seu Cliente MCP
OpenClaw
openclaw mcp register mnemon-mcp --command="mnemon-mcp"
Ou adicione ao ~/.openclaw/mcp_config.json:
{
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
Claude Code
Adicione ao ~/.claude/mcp.json:
{
"mcpServers": {
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
}
Cursor / Windsurf / Outros clientes MCP
Adicione à configuração MCP do seu cliente:
{
"mcpServers": {
"mnemon-mcp": {
"command": "mnemon-mcp"
}
}
}
Executando a partir do código-fonte?
Use o caminho completo para o ponto de entrada compilado:
{
"mnemon-mcp": {
"command": "node",
"args": ["/absolute/path/to/mnemon-mcp/dist/index.js"]
}
}
Verificação
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | mnemon-mcp
Você deve ver 10 ferramentas na resposta. O banco de dados (~/.mnemon-mcp/memory.db) é criado automaticamente na primeira execução.
É isso. Seu agente agora tem memória persistente.
O Que Ele Pode Fazer
10 Ferramentas MCP
| Ferramenta | O que faz |
|---|---|
memory_add | Armazena uma memória com camada, entidade, confiança, importância e TTL opcional |
memory_search | Busca de texto completo ou exata com filtros por camada, entidade, data, escopo, confiança |
memory_update | Atualiza no local ou cria uma substituição versionada (cadeia de substituição) |
memory_delete | Exclui uma memória; reativa seu predecessor, se houver |
memory_inspect | Obtém estatísticas de camada ou rastreia o histórico de versões de uma única memória |
memory_export | Exporta para JSON, Markdown ou formato Claude-md com filtros |
memory_health | Executa diagnósticos: entradas expiradas, cadeias órfãs, memórias obsoletas; opcionalmente GC |
memory_session_start | Inicia uma sessão de agente — retorna ID de sessão para agrupar memórias |
memory_session_end | Encerra uma sessão com resumo opcional; retorna duração e contagem de memórias |
memory_session_list | Lista sessões com filtros por cliente, projeto ou status ativo |
Recursos e Prompts MCP
Recursos — dados ao vivo que seu agente pode ler:
| URI | Retorna |
|---|---|
memory://stats | Estatísticas agregadas por camada |
memory://recent | Memórias criadas/atualizadas nas últimas 24h |
memory://layer/{layer} | Todas as memórias ativas em uma camada |
memory://entity/{name} | Todas as memórias ativas sobre uma entidade |
Prompts — fluxos de trabalho pré-construídos:
| Prompt | Propósito |
|---|---|
recall | "Conte-me tudo o que você sabe sobre X" |
context-load | Carrega contexto relevante antes de iniciar uma tarefa |
journal | Cria uma entrada de diário estruturada |
Busca
Quatro modos, todos com suporte a filtros de camada / entidade / escopo / data / confiança:
Modo FTS (padrão sem embeddings) — busca de texto completo tokenizada com ranking BM25. Consultas com múltiplas palavras usam AND; se houver poucos resultados, OR complementa com penalidade de pontuação. Relaxamento progressivo de AND tenta os 3 termos mais específicos antes de cair para OR completo.
Modo Híbrido (padrão quando embeddings estão configurados) — combina FTS5 + busca vetorial via Fusão de Rank Recíproco. Detecta entidades entre aspas em consultas (ex.: 'Essentialism') e executa sub-consultas ponderadas para recuperação de referências cruzadas.
Modo Vetorial — busca pura de similaridade por cosseno sobre embeddings.
Modo Exato — LIKE correspondência de substring para buscas precisas de frases.
Pontuações: bm25 × (0.3 + 0.7 × importance) × decay(layer) × recency
Impulso de recência: 1 / (1 + daysSince / 365) — recompensa suavemente memórias criadas recentemente sem penalizar as antigas.
Stemming
Stemmer Snowball aplicado tanto no momento da indexação quanto no momento da consulta para inglês e russo. Isso significa que "running" corresponde a "runs", e "книги" corresponde a "книга". Palavras de parada são filtradas das consultas para melhorar a precisão.
Versionamento de Fatos
O conhecimento evolui. O Mnemon não exclui fatos antigos — ele os encadeia:
v1: "Team uses React 17" → superseded_by: v2
v2: "Team uses React 19" → supersedes: v1 (active)
A busca retorna apenas a versão mais recente. memory_inspect com include_history: true revela a cadeia completa. memory_delete reativa o predecessor — nada é perdido.
Busca Vetorial (Opcional, BYOK)
Habilite a busca de similaridade semântica fornecendo sua própria API de embeddings:
# OpenAI
MNEMON_EMBEDDING_PROVIDER=openai MNEMON_EMBEDDING_API_KEY=sk-... mnemon-mcp
# Ollama (local, free)
MNEMON_EMBEDDING_PROVIDER=ollama mnemon-mcp
Isso desbloqueia dois modos de busca adicionais:
mode: "vector"— busca pura de similaridade por cossenomode: "hybrid"— FTS5 + vetor combinados via Fusão de Rank Recíproco
Requer sqlite-vec (instalado como dependência opcional). Novas memórias são incorporadas na adição; as existentes podem ser preenchidas retroativamente.
Configuração de embeddings
| Variável | Padrão | Descrição |
|---|---|---|
MNEMON_EMBEDDING_PROVIDER | — | openai ou ollama (não definido = desabilitado) |
MNEMON_EMBEDDING_API_KEY | — | Chave de API (obrigatória para OpenAI) |
MNEMON_EMBEDDING_MODEL | text-embedding-3-small / nomic-embed-text | Nome do modelo |
MNEMON_EMBEDDING_DIMENSIONS | 1024 / 768 | Dimensões do vetor |
MNEMON_OLLAMA_URL | http://localhost:11434 | Endpoint do Ollama |
Importando uma Base de Conhecimento
Tem uma pasta de arquivos Markdown? Importe-os em massa:
cp config.example.json ~/.mnemon-mcp/config.json # edit this first
npm run import:kb -- --kb-path /path/to/your/kb # incremental (skips unchanged files)
A configuração mapeia padrões glob para camadas de memória:
{
"owner_name": "your-name",
"extra_stop_words": [],
"mappings": [
{
"glob": "journal/*.md",
"layer": "episodic",
"entity_type": "user",
"entity_name": "$owner",
"importance": 0.6,
"split": "h2"
},
{
"glob": "people/*.md",
"layer": "semantic",
"entity_type": "person",
"entity_name": "from-heading",
"importance": 0.8,
"split": "h3"
}
]
}
Campos de Configuração
| Campo | Tipo | Descrição |
|---|---|---|
owner_name | string | Seu nome — usado para substituição de $owner em entity_name |
extra_stop_words | string[] | Palavras para filtrar de consultas FTS (ex.: formas do seu nome) |
glob | string | Padrão de arquivo para correspondência |
layer | string | Camada de memória de destino |
entity_type | string | user / person / project / concept / file / rule / tool |
entity_name | string | Nome literal, "$owner" ou "from-heading" (extrair de H2/H3) |
split | string | "whole" (uma memória por arquivo), "h2" ou "h3" (dividir em títulos) |
importance | number | 0.0–1.0, afeta o ranking de busca |
confidence | number | 0.0–1.0, filtrável na busca |
scope | string | Namespace opcional |
Transporte HTTP
Para configurações remotas ou com múltiplos clientes:
MNEMON_AUTH_TOKEN=your-secret MNEMON_HOST=0.0.0.0 MNEMON_PORT=3000 npm run start:http
| Endpoint | Descrição |
|---|---|
POST /mcp | MCP JSON-RPC (autenticação Bearer se o token estiver definido) |
GET /health | {"status":"ok","version":"..."} |
Vincula a 127.0.0.1 por padrão. Vincular a qualquer outro host requer MNEMON_AUTH_TOKEN — o servidor se recusa a expor o armazenamento de memória à rede sem autenticação (substituível com MNEMON_ALLOW_INSECURE_HTTP=1 em uma rede confiável). Limitação de taxa (100 req/min/IP por padrão), CORS opcional, limite de corpo de 1MB, autenticação segura contra timing, desligamento gracioso em SIGTERM.
Referência de Configuração
| Variável | Padrão | Descrição |
|---|---|---|
MNEMON_DB_PATH | ~/.mnemon-mcp/memory.db | Caminho do banco de dados |
MNEMON_KB_PATH | . | Raiz da base de conhecimento para importação |
MNEMON_CONFIG_PATH | ~/.mnemon-mcp/config.json | Caminho da configuração de importação |
MNEMON_AUTH_TOKEN | — | Token Bearer para transporte HTTP |
MNEMON_HOST | 127.0.0.1 | Endereço de vinculação do transporte HTTP |
MNEMON_PORT | 3000 | Porta do transporte HTTP |
MNEMON_CORS_ORIGIN | — | CORS Access-Control-Allow-Origin (sem cabeçalhos CORS a menos que definido) |
MNEMON_RATE_LIMIT | 100 | Máximo de requisições por minuto por IP (0 = desligado) |
Referência de Ferramentas
memory_add — lista completa de parâmetros
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
content | string | Sim | Texto da memória (máx. 100K caracteres) |
layer | string | Sim | episodic / semantic / procedural / resource |
title | string | Não | Título curto (máx. 500 caracteres) |
entity_type | string | Não | user / project / person / concept / file / rule / tool |
entity_name | string | Não | Nome da entidade para filtragem |
confidence | number | Não | 0.0–1.0 (padrão 0.8) |
importance | number | Não | 0.0–1.0 (padrão 0.5) |
scope | string | Não | Namespace (padrão global) |
source_file | string | Não | Caminho do arquivo de origem — aciona auto-substituição de entradas correspondentes |
ttl_days | number | Não | Auto-expiração após N dias |
valid_from / valid_until | string | Não | Janela de fato temporal (ISO 8601) |
memory_search — lista completa de parâmetros
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
query | string | Sim | Texto de busca |
mode | string | Não | fts (padrão), exact, vector, hybrid |
layers | string[] | Não | Filtrar por camadas |
entity_name | string | Não | Filtrar por entidade (suporta aliases) |
scope | string | Não | Filtrar por escopo |
date_from / date_to | string | Não | Intervalo de datas (ISO 8601) |
as_of | string | Não | Filtro de fato temporal — fatos válidos nesta data |
min_confidence | number | Não | Confiança mínima |
min_importance | number | Não | Importância mínima |
limit | number | Não | Máximo de resultados (padrão 10, máximo 100) |
offset | number | Não | Deslocamento de paginação |
memory_update — lista completa de parâmetros
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | ID da memória |
content | string | Não | Novo conteúdo |
title | string | Não | Novo título |
confidence | number | Não | Nova confiança |
importance | number | Não | Nova importância |
supersede | boolean | Não | true = substituição versionada; false (padrão) = no lugar |
new_content | string | Não | Conteúdo para entrada substituta |
memory_delete
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | ID da memória. Reativa o predecessor se fizer parte de uma cadeia de substituição |
memory_inspect
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Não | ID da memória (omitir para estatísticas agregadas) |
layer | string | Não | Filtrar estatísticas por camada |
entity_name | string | Não | Filtrar estatísticas por entidade |
include_history | boolean | Não | Mostrar cadeia de substituição |
memory_export
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
format | string | Sim | json / markdown / claude-md |
layers | string[] | Não | Filtrar por camadas |
scope | string | Não | Filtrar por escopo |
date_from / date_to | string | Não | Intervalo de datas |
limit | number | Não | Máximo de entradas (padrão todas, máximo 10 mil) |
memory_health
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
cleanup | boolean | Não | true = coletar lixo de entradas expiradas (padrão: apenas relatar) |
Retorna: status (healthy / warning / degraded), estatísticas por camada, entradas expiradas, cadeias órfãs, contagens obsoletas/baixa confiança, contagem limpa quando cleanup=true.
memory_session_start
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
client | string | Sim | Identificador do cliente (ex.: claude-code, cursor, api) |
project | string | Não | Escopo do projeto para esta sessão |
meta | object | Não | Metadados adicionais da sessão |
Retorna: id (UUID da sessão), started_at (ISO 8601).
memory_session_end
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | ID da sessão a encerrar |
summary | string | Não | Resumo do que foi realizado (máx. 10 mil caracteres) |
Retorna: id, ended_at, duration_minutes, memories_count.
memory_session_list
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
limit | number | Não | Máximo de sessões (padrão 20, máximo 100) |
client | string | Não | Filtrar por cliente |
project | string | Não | Filtrar por projeto |
active_only | boolean | Não | Retornar apenas sessões não encerradas (padrão falso) |
Retorna: array de sessões com id, client, project, started_at, ended_at, summary, memories_count.
Como se Compara
| mnemon-mcp | mem0 | basic-memory | Engram | Anthropic KG | |
|---|---|---|---|---|---|
| Arquitetura | SQLite FTS5 + vetorial | API em nuvem + Qdrant | Markdown + vetorial | SQLite FTS5 | Arquivo JSON |
| Estrutura de memória | 4 camadas tipadas | Plana | Plana | Plana + sessões | Grafo |
| Busca | FTS5 + híbrida RRF | Semântica | Híbrida | FTS5 | Exata |
| Versionamento de fatos | Cadeias de substituição | Parcial | Não | Não | Não |
| Stemming | EN + RU (Snowball) | Somente EN | Somente EN | Nenhum | Nenhum |
| Embeddings | BYOK (OpenAI / Ollama) | Integrado | FastEmbed | Nenhum | Nenhum |
| Dependências | 0 obrigatórias | Qdrant, Neo4j | Python 3.12 | Binário Go | Nenhuma |
| Nuvem obrigatória | Não | Sim | Não | Não | Não |
| Custo | Gratuito | $19–249/mês | Gratuito | Gratuito | Gratuito |
| Configuração | npm install -g | Docker + chaves de API | pip + dependências | Instalação Go | Integrado |
| Licença | MIT | Apache 2.0 | AGPL | MIT | MIT |
Análise competitiva estendida com fontes: docs/COMPETITORS.md.
Desenvolvimento
npm run dev # run via tsx (no build step)
npm run build # TypeScript → dist/
npm run lint # eslint (flat config)
npm test # vitest — unit + integration + MCP dispatch + HTTP transport + hybrid RRF
npm run bench # performance benchmarks
npm run db:backup # backup database
O CI executa build + lint + testes no Node 20 e 22, depois faz smoke-tests do servidor compilado
via JSON-RPC real (tools/list deve corresponder ao conjunto exato de ferramentas).
Stack: TypeScript 5.9 (modo estrito), better-sqlite3, @modelcontextprotocol/sdk, stemmer Snowball, Zod, vitest.
Consulte CONTRIBUTING.md para diretrizes de código.
Princípios de Design
- Isolado por padrão — zero telemetria, sempre. Fora da caixa, nada sai da máquina; o único componente que fala com a rede é o embedder opcional, e apenas com o provedor que você configurar (incluindo um Ollama local).
- Arquivo único — um banco de dados SQLite, zero operações, backup instantâneo via cópia de arquivo.
- Busca determinística — FTS5, não embeddings, é o padrão. Interpretável, reproduzível, sem necessidade de GPU.
- Estruturado em vez de plano — camadas codificam padrões de acesso; cadeias de substituição codificam tempo.
- Mínimo — 4 dependências de produção. Funciona em qualquer lugar onde o Node roda.
- Medido, não presumido — mudanças na recuperação são avaliadas contra um conjunto dourado, regressões incluídas.