Каждый, кто пробовал строить агентов на LLM, знает эту боль: вы даете задачу, модель блестяще её выполняет, а в следующем диалоге она ведет себя так, будто предыдущий разговор был в параллельной вселенной. Долговременная память — та самая функция, которая превращает статичный чат-бот в настоящего ассистента. Но пока большинство решений либо завязаны на облачные API, либо используют примитивный поиск по ключевым словам, теряя смысловой контекст.
Встречайте Memory MCP — открытый проект, который реализует гибридный поиск для памяти LLM через протокол MCP. Он объединяет три подхода: классический BM25 (лексический), векторные эмбеддинги (семантический) и RRF (Reciprocal Rank Fusion) для ранжирования результатов. А эмбеддинги в нем считает локальная Qwen3.5-4B — легкая модель, которая справляется с генерацией векторов без выноса GPU. Если вы уже знакомы с концепцией MCP и его преимуществами перед традиционными инструментами автоматизации, вам будет особенно приятно увидеть, как тот же протокол решает проблему памяти — об этом я подробно писал в статье «Как я выбросил Ansible и Jenkins в окно: MCP и локальные LLM как новый стек автоматизации».
Что под капотом: BM25 + вектора + RRF
Memory MCP хранит «воспоминания» в виде пар ключ-значение с текстовым описанием. Когда вы задаете вопрос, сервер ищет релевантные записи тремя способами одновременно:
- BM25 — классический TF-IDF, который отлично находит точные совпадения терминов.
- Векторный поиск — эмбеддинги от Qwen3.5-4B (или любой другой модели через llama.cpp/vLLM). Это ловит смысл фразы, даже если слова не совпадают.
- RRF — финальная сортировка объединенных результатов: каждый документ получает ранг
1/(k + rank), и чем выше сумма по всем методам, тем выше итоговая позиция.
Звучит логично, но на практике гибрид даёт заметно больше адекватных ответов, чем каждый из методов по отдельности. Я тестировал на дампе своих рабочих заметок — чисто векторный поиск терял имена и точные даты, чистый BM25 игнорировал перефразировки. А вместе — красота.
💡 Проект полностью локальный: никаких сторонних API для памяти, только ваша железка. Эмбеддинги можно гонять даже на встроенной графике ноутбука — Qwen3.5-4B в 4-битном квантовании жрет около 3.5 ГБ VRAM. Подробнее про квантования этой модели читайте в обзоре «Скрытые жемчужины Qwen 3.5».
Установка: три способа на выбор
Memory MCP можно поставить через pip, uv (быстрый Rust-аналог pip) или Docker. Самый простой вариант — uv, он ставит зависимости в разы быстрее. Не советую так делать, если хотите прозрачности — uv всё равно под капотом дергает PyPI, но кэширование агрессивное.
# Через uv (рекомендую)
uv tool install memory-mcp
# Или через pip
pip install memory-mcp
# Или Docker (для изоляции)
docker pull ghcr.io/mcp/memory-mcp:latestПосле установки нужно указать, где лежит модель эмбеддингов. По умолчанию сервер ищет Qwen3.5-4B-GGUF в директории ~/.cache/memory-mcp/. Если у вас уже есть GGUF-файл этой модели — просто скопируйте или создайте ссылку. Если нет, скачайте, например, из репозитория CatalystSec — в моей статье о лучших квантованиях есть проверенные ссылки, которые не отвалятся через месяц.
Глобально конфиг лежит в memory_config.json:
{
"embedding": {
"model_path": "/models/qwen3.5-4b-Q4_K_M.gguf",
"backend": "llama.cpp"
},
"memory": {
"store_path": "./memory_store",
"k_bm25": 20,
"k_vector": 20,
"rrf_k": 60
},
"mcp": {
"transport": "stdio"
}
}Запуск и первые тесты
Запускаем сервер:
memory-mcp --config memory_config.jsonПо умолчанию он использует transport stdio — это значит, что общение с MCP-клиентом идет через stdin/stdout. Отлично подходит для Claude Desktop, Continue.dev, Cursor IDE и других инструментов, поддерживающих MCP. Если хотите сетевой доступ, укажите "transport": "sse" и порт.
Первый запрос будет медленным — сервер загрузит модель и проиндексирует хранилище. Дальше — летает: типичное время поиска по 10 000 записей — 50–150 мс на CPU с 8 ядрами.
⚠️ Если вы используете Qwen3.5-4B для генерации текста, могли столкнуться с багом, когда модель начинает нести чушь после 2–3 ответов. Я разбирал эту проблему в статье «Исправление ошибки: Qwen 3.5 выводит бессмыслицу после 2-3 ответов». Хорошая новость: для эмбеддингов этот баг неактуален — Memory MCP использует модель только для forward pass, без генерации, так что стабильность 100%.
Сравнение с альтернативами
| Характеристика | Memory MCP | Mem0 | LangMem | Обычный RAG |
|---|---|---|---|---|
| Локальность | Полностью локальный | Облачный API | Требует БД | Зависит от стека |
| Поиск | Гибрид (BM25+вектора+RRF) | Векторный + лексический | Только RAG (часто без BM25) | Обычно только вектора |
| MCP-совместимость | Из коробки (stdio/SSE) | Через отдельный адаптер | Нет встроенной | Нужна обертка |
| Стоимость | Бесплатно (open source) | $0.01/запись | Бесплатно, но сложнее | Зависит от инфры |
| Размер эмбеддинг-модели | Любая (по умолчанию Qwen3.5-4B) | Закрытая проприетарная | Любая (через LangChain) | Любая |
Memory MCP явно выигрывает в простоте интеграции с экосистемой MCP и в качестве поиска за счет гибрида. Mem0 быстрее стартануть (облачный API), но вы платите за каждую запись и теряете контроль над данными. LangMem — мощный, но громоздкий: это часть LangGraph, и для простого сохранения контекста его разворачивать — как стрелять из пушки по воробьям. Обычный RAG (Chroma + embeddings) — неплохой вариант, но без BM25 вы пропускаете точные вхождения, особенно если пользователь вводит запрос дословно. Если вы собираете homelab на одной машине и хотите заменить три отдельных LLM одной MoE-моделью (как описано в статье про замену трёх LLM на одну MoE 122B), Memory MCP станет идеальным компактным модулем памяти, который не тянет за собой лишних зависимостей.
Интеграция с клиентами: реальный пример
Допустим, вы используете Claude Desktop и хотите, чтобы он помнил ваши предпочтения между диалогами. Пропишите MCP-сервер в конфиг:
{
"mcpServers": {
"memory": {
"command": "memory-mcp",
"args": ["--config", "/home/user/memory_config.json"],
"env": {},
"disabled": false,
"autoApprove": []
}
}
}После перезапуска Claude вы можете просто сказать: «Запомни, что я предпочитаю отвечать на письма в краткой форме». Claude вызовет инструмент memory.set, сохранит запись, и в следующий раз при генерации письма извлечет это воспоминание через memory.search. А если у вас есть тулы для работы с файлами (например, через MCP-сервер файловой системы), комбинация получается очень мощной.
Аналогично настраивается для Continue.dev — достаточно добавить блок в .continuerc.json:
"tools": [
{
"name": "memory",
"type": "mcp",
"command": "memory-mcp",
"args": ["--config", "./memory_config.json"]
}
]Теперь ваш coding assistant помнит, какой стиль кода вы предпочитаете, какие библиотеки используете чаще, и не забывает комментарии к сложным функциям.
Кому это реально нужно
Memory MCP — не панацея, но в нескольких сценариях он незаменим:
- Разработчики AI-агентов — если вы строите многозадачного ассистента, которому нужно помнить контекст сотен диалогов. Встраивание Memory MCP через MCP протокол занимает 10 минут, а точность поиска критична.
- Homelab-энтузиасты — у вас есть локальный сервер с GPU (например, RTX 3060 или даже старая P40). Qwen3.5-4B встанет на любую карту с 4+ ГБ VRAM. Если же у вас совсем скромное железо, обратите внимание на Liquid AI LFM2-2.6B — эта модель еще легче и тоже подходит для эмбеддингов, хотя качество векторов чуть ниже.
- Команды, которые хотят privacy-first — никакие данные не уходят за пределы вашей сети. Идеально для юридических, медицинских или финансовых приложений.
Не советую так делать, если вы рассчитываете на память для миллионов записей — текущая версия хранит всё в SQLite, и при >100k записей скорость поиска падает. Но для типового использования (10–50 тысяч фактов) это отличный вариант.
В итоге Memory MCP — это тот редкий случай, когда open-source проект решает конкретную боль без оверкилла. Никаких танцев с бубном вокруг LangChain, никаких кредиток для API. Просто установил, скормил GGUF-файл, и LLM перестает быть амнезиком. Попробуйте — возможно, именно этого не хватало вашему агенту.