Mémoire persistante, hybride et locale pour agents LLM — serveur MCP + API REST + SDK Python.
LLM Memory Tool stocke les connaissances, décisions et conventions d'un projet, puis fournit le contexte pertinent à injecter dans les prompts, sans jamais dépasser un budget de tokens. Recherche hybride vectorielle + BM25 avec fusion RRF, graphe de connaissances, moteur de politiques (décroissance, rétention, renforcement) et serveur MCP pour une intégration directe dans les assistants (VS Code, opencode, Claude…).
- Recherche hybride : similarité cosinus (vecteurs) + full-text BM25 + fusion RRF
- 4 types de mémoire :
semantic,episodic,procedural,profile - Injection pilotée par budget : jamais au-delà du plafond de tokens configuré
- Moteur de politiques : décroissance de confiance, renforcement, rétention/élagage
- Graphe de connaissances : entités, relations typées, parcours, plus court chemin, clustering (KMeans/DBSCAN) et extraction d'entités par NLP (spaCy)
- Génération de skills : transforme un cluster du graphe en fiche
SKILL.md - API REST : FastAPI + spec OpenAPI auto-générée sur
/docs - SDK Python : un appel
get_context(query, project_id)pour le contexte de prompt - Serveur MCP : 20+ outils exposés (
memory_store,memory_retrieve,graph_*…) - Observabilité : métriques Prometheus, logs structurés
- Docker : conteneur de production avec service d'embeddings (Ollama) intégré
┌──────────────┐ stdio / MCP ┌──────────────────┐ HTTP :8765 ┌──────────────────┐
│ Assistant │ ◄──────────────► │ Serveur MCP │ ─────────────► │ API REST │
│ (opencode, │ │ mcp_server/ │ (MEMORY_API_URL)│ memory_tool/ │
│ VS Code…) │ │ server.py │ ◄───────────── │ (FastAPI) │
└──────────────┘ └──────────────────┘ HTTP :8765 └────────┬─────────┘
│
┌───────┴────────┐
│ SQLite │
│ /data/memory.db│
└────────────────┘
┌──────────────────┐ HTTP :11434
│ Ollama │ ◄────── embeddings (nomic-embed-text)
│ (conteneur) │
└──────────────────┘
- API (
memory_tool/) : FastAPI, port8765, endpoints sous/api/v1 - Serveur MCP (
mcp_server/) : transport stdio, s'appuie sur l'API viaMEMORY_API_URL - UI : accessible sur
http://localhost:8766(optionnelle, voir docker-compose)
| Outil | Version minimum |
|---|---|
| Python | 3.11+ (3.13 testé) |
| Docker | 24+ (recommandé, avec plugin compose) |
| pip | 23+ |
cd memory_tool/
cp .env.example .env # définir MEMORY_API_KEY
docker compose up -d --build # démarre API :8765 + embeddings Ollama
curl http://localhost:8765/api/v1/healthLe service embeddings télécharge nomic-embed-text au premier démarrage.
cd memory_tool/
python -m venv .venv
source .venv/bin/activate # Windows : .venv\Scripts\activate
pip install -e ".[dev]"
# Pour le NLP (spaCy) : python -m spacy download en_core_web_sm
MEMORY_API_KEY=changeme MEMORY_EMBED_MODEL=mock uvicorn memory_tool.app:app --port 8765Ajoutez ce bloc à votre opencode.json (ou équivalent pour VS Code / Claude) :
{
"mcp": {
"llm-memory-tool": {
"type": "local",
"command": ["python", "-m", "mcp_server.server"],
"environment": {
"MEMORY_API_URL": "http://localhost:8765/api/v1",
"MEMORY_API_KEY": "changeme",
"MEMORY_DEFAULT_PROJECT": "default"
},
"enabled": true
}
}
}Le serveur MCP parle à l'API sur MEMORY_API_URL (défaut : http://localhost:8765/api/v1).
| Outil | Rôle |
|---|---|
memory_health |
Vérifie que l'API est joignable |
memory_store |
Stocke une mémoire (type, tags, importance) |
memory_retrieve |
Récupère le contexte prêt à injecter (budget tokens) |
memory_retrieve_graph_augmented |
Recherche augmentée par le graphe de connaissances |
memory_list / memory_get |
Parcours et lecture des mémoires |
memory_update / memory_delete |
Mise à jour / suppression (soft ou hard) |
memory_consolidate |
Applique décroissance/rétention (dry-run par défaut) |
graph_entity_create / graph_entity_search / graph_entity_get |
Entités du graphe |
graph_edge_create / graph_edge_list |
Relations typées entre nœuds |
graph_traverse / graph_shortest_path |
Exploration du graphe (BFS, plus court chemin) |
graph_cluster |
Clustering KMeans/DBSCAN des entités |
graph_discover_entities |
Extraction d'entités par NLP (spaCy) |
graph_skill_sync / graph_skill_sync_all |
Génération de fiches SKILL.md |
# Stocker une mémoire
curl -X POST http://localhost:8765/api/v1/memories \
-H "X-API-Key: changeme" \
-H "Content-Type: application/json" \
-d '{"project_id": "my-project",
"content": "On utilise FastAPI pour tous les endpoints REST, pydantic v2 pour la validation.",
"memory_type": "procedural",
"tags": ["architecture", "fastapi"]}'
# Récupérer le contexte
curl -X POST http://localhost:8765/api/v1/retrieve \
-H "X-API-Key: changeme" \
-H "Content-Type: application/json" \
-d '{"query": "quel framework pour les APIs ?", "project_id": "my-project", "token_budget": 600}'from memory_tool.sdk import MemoryClient, get_context
client = MemoryClient(api_key="changeme")
client.create_memory(
project_id="my-project",
content="Convention : snake_case pour toutes les fonctions Python.",
tags=["conventions"],
)
context = get_context("conventions de nommage", project_id="my-project")
prompt = f"Contexte :\n{context}\n\nUtilisateur : {user_message}"memory_retrieved'abord — injectez le contexte pertinent dans votre prompt ;- après une interaction utile,
memory_storepour persister la nouvelle connaissance ; memory_consolidatepériodiquement pour appliquer les politiques.
Toutes les réglages passent par des variables préfixées MEMORY_ (fichier .env supporté) :
| Variable | Défaut | Description |
|---|---|---|
MEMORY_DB_PATH |
/data/memory.db |
Chemin SQLite |
MEMORY_API_KEY |
changeme |
À changer en production |
MEMORY_EMBED_MODEL |
local |
local / mock |
MEMORY_EMBED_URL |
http://localhost:11434 |
URL Ollama / LM Studio |
MEMORY_EMBED_MODEL_NAME |
nomic-embed-text |
Modèle d'embedding |
MEMORY_TOP_K |
5 |
k par défaut de la recherche |
MEMORY_MAX_TOKEN_BUDGET |
1500 |
Plafond de tokens injectés |
MEMORY_DECAY_DAYS |
30 |
Jours avant décroissance de confiance |
MEMORY_RETENTION_DAYS |
90 |
Rétention par défaut |
MEMORY_API_URL |
http://localhost:8765/api/v1 |
URL de l'API (côté MCP/SDK) |
MEMORY_DEFAULT_PROJECT |
default |
Projet par défaut (MCP) |
cd memory_tool/
pytest tests/ -q # 38 tests (SQLite en mémoire, aucun service externe requis)
# Avec couverture
pytest --cov=memory_tool --cov-report=term-missing
# Lint
ruff check memory_tool/Les tests utilisent une base SQLite en mémoire : aucune API Docker n'est nécessaire.
memory_tool/
├── mcp_server/ # Serveur MCP (stdio) : server.py, client.py
├── memory_tool/ # API FastAPI
│ ├── app.py # Point d'entrée FastAPI
│ ├── auth.py # Authentification par clé API
│ ├── config.py # Paramètres (pydantic-settings, env MEMORY_*)
│ ├── dependencies.py # Injection de dépendances
│ ├── sdk.py # Client SDK Python
│ ├── adapters/ # Embeddings (Ollama/mock), graphe
│ ├── db/ # Schéma SQLite + migrations + repository
│ ├── domain/ # Modèles métier purs + exceptions
│ ├── routers/ # Endpoints REST (memories, retrieve, admin, graph, infra)
│ └── services/ # mémoire, recherche hybride, politiques, NLP, clustering, skills
├── scripts/ # Synchronisation de l'index des skills, évaluation Recall@K
├── tests/ # Suite pytest
├── docs/ # Documentation (skill-index)
├── Dockerfile
├── docker-compose.yml # API :8765 + embeddings Ollama + UI :8766
├── pyproject.toml
└── requirements.txt
MIT © 2026 Jean-Luc KOUMAGLO (menoxz)