Skip to main content
Glama

LLM Second Brain

License: MIT Python 3.12 Docker

Self-hosted MCP-сервер «второго мозга» для LLM, крутящихся в харнесах (в первую очередь — Open WebUI). Модели получают через MCP доступ к общему банку заметок: могут искать по нему (гибридный векторный + полнотекстовый поиск), просматривать, записывать, обновлять и удалять заметки.

Зачем

  1. Распределённые знания с быстрым доступом. Знания живут не в системном промпте и не в истории чатов, а в отдельном хранилище; модель получает только релевантное, по запросу.

  2. Экономия токенов. Вместо монолитного контекста — фиксированный небольшой overhead на спецификацию инструментов (~1200 токенов) и адресная выдача кратких содержаний заметок, а не целых текстов.

Related MCP server: Project Memory MCP Server

Ключевые свойства

  • Один контейнер Docker, self-host, non-root.

  • MCP Streamable HTTP (/mcp, нативно поддерживается Open WebUI) + Bearer-токен.

  • 6 инструментов с префиксом memory_*: search, list, get, save, update, delete.

  • Хранилище: SQLite + sqlite-vec (векторный поиск) + FTS5 (полнотекстовый), слияние через Reciprocal Rank Fusion.

  • Векторизация: внешний Ollama (embedding-модель и адрес — в env); вектора строятся по чанкам текста (сама заметка хранится целиком) — поиск по факту из середины длинной заметки не «размазывается» (см. «Чанковая индексация»).

  • Суммаризация: отдельная внешняя LLM (адрес и модель — в env) строит короткое summary каждой заметки; модели через MCP получают компактные выдачи (id, summary, метки времени), полный контракт поиска — у REST (GET /search): snippet (фрагмент лучшего чанка), cosine, rrf_score, author. Генерация — фоновая, не блокирует запись; рассуждения модели не сохраняются.

  • Резервное копирование: периодический онлайн-снапшот БД в BACKUP_DIR (SQLite backup API), ротация по BACKUP_KEEP.

  • Логи — одна JSON-строка на событие в stdout (вызовы инструментов с латентностью и числом результатов; тексты запросов — первые 80 символов; содержимое заметок в логи не пишется).

  • Пользовательского интерфейса нет — пишут и читают только модели; оператор имеет доступ к файлу БД напрямую.

Документация

  • Требования — цели, функциональные и нефункциональные требования, контракты всех инструментов, конфигурация (§8), риски.

  • Архитектура — компоненты, схема данных, потоки, интеграция с Open WebUI, подход к «обучению» моделей, тестирование, деплой.

Быстрый старт (docker compose)

git clone <repo> llm-second-brain && cd llm-second-brain
# Вся конфигурация — в docker-compose.yml (без .env).
# Обязательное там же:
#   OLLAMA_BASE_URL, SUMMARY_OLLAMA_BASE_URL, SUMMARY_MODEL,
#   MCP_AUTH_TOKEN  (сгенерируй: openssl rand -hex 32)
# Дефолты всех прочих переменных — канонические из REQUIREMENTS §8, видно
# рядом с каждой; фактические значения переопределяются там же, в compose.
mkdir -p data          # каталог volume: notes.db + backups (uid/gid 1000)
docker compose up -d --build
curl -s http://localhost:8080/health | python -m json.tool

/health отвечает без токена:

{"status":"ok","embedding_ok":null,"summarizer_ok":null,
 "notes_count":0,"pending_vector":0,"pending_summary":0}

embedding_ok/summarizer_ok — исход последних попыток (null — попыток ещё не было; обеих Ollama может не быть на старте — сервис поднимется штатно, записи уйдут в pending и догонятся фоновым воркером, NFR-3).

Подключение Open WebUI

Требуется Open WebUI v0.6.31+ — с этой версии поддерживается MCP Streamable HTTP нативно.

  1. Открой Admin Panel → Settings → Integrations → блок «External Tool Servers» → «+ Add Connection» (в старых версиях пункт называется «Tools → Add Connection»).

  2. Заполни поля диалога:

    • Type: MCP Streamable HTTP;

    • URL: http://<хост-сервиса>:8080/mcp — путь MCP_PATH, по умолчанию /mcp. Если Open WebUI в другом контейнере того же docker-хоста → http://<ip-хоста>:8080/mcp (или имя сети compose);

    • Auth: Bearer; token — значение MCP_AUTH_TOKEN из docker-compose.yml.

  3. Сохрани. В списке появятся 6 инструментов memory_* — они доступны всем моделям, достаточно включить у модели «вызов инструментов».

  4. Проверка в чате: «найди в памяти …» → модель вызывает memory_search.

Дополнительные MCP-клиенты подключаются так же: URL http://<host>:8080/mcp, заголовок Authorization: Bearer <MCP_AUTH_TOKEN>. Handshake curl'ом:

curl -s http://localhost:8080/mcp \
  -H "Authorization: Bearer $MCP_AUTH_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

Конфигурация

Вся конфигурация — в docker-compose.yml, блок environment (все 42 переменных §8 с дефолтами; фактические значения правятся там же, .env нет). Обязательные — OLLAMA_BASE_URL, SUMMARY_OLLAMA_BASE_URL, SUMMARY_MODEL, MCP_AUTH_TOKEN (пустой токен — фатальная ошибка старта). Канонические дефолты снять из REQUIREMENTS §8, ключевые:

Переменная

Умолчание

Смысл

MCP_AUTH_TOKEN

— (обязателен)

Bearer-токен всех ручек, кроме /health

OLLAMA_BASE_URL

— (обязателен)

Ollama векторизации (/api/embed)

SUMMARY_OLLAMA_BASE_URL

— (обязателен)

Ollama суммаризации (/api/chat)

SUMMARY_MODEL

— (обязателен)

модель суммаризации, напр. ornith-1.5:35b

EMBEDDING_MODEL / EMBEDDING_DIM

qwen3-embedding:8b / 4096

embedding; смена модели/размерности — автоматическая реиндексация при старте (все заметки уходят в pending, воркер пере-кодирует)

PORT / MCP_PATH

8080 / /mcp

HTTP и путь MCP

DB_PATH

/data/notes.db

файл SQLite (WAL)

BACKUP_DIR / BACKUP_INTERVAL_SEC / BACKUP_KEEP

/data/backups / 86400 / 7

снапшоты: каталог, интервал, ротация

LOG_LEVEL

INFO

уровень JSON-логов stdout

MAX_NOTE_CHARS / MAX_QUERY_CHARS

35000 / 512

лимиты ввода

TEXT_SPLITTER

tiktoken

токен-сплиттер чанков (encoding cl100k_base, кэш в образе)

CHUNK_SIZE / CHUNK_OVERLAP / CHUNK_MIN_TARGET

1024 / 180 / 200

окно чанка (токенов), перекрытие, минимальный хвост; смена любого — полная пере-чанковка при старте

EMBEDDING_BATCH_SIZE / EMBEDDING_CONCURRENT_REQUESTS

32 / 3

воркер чанков: чанков в одном embed-запросе / параллельных запросов

Все лимиты валидируются при старте: некорректное значение (вне диапазона, мусор) — фатальная ошибка конфигурации с перечнем всех нарушений сразу. Смена MAX_NOTE_CHARS поверх существующей БД запрещена (лимит «запечён» в CHECK-схеме) — верни прежнее значение или пересоздай БД.

Чанковая индексация

Вектора строятся не «один на заметку», а по чанкам: заметка хранится и отдаётся целиком, но для векторизации текст режется сплиттером (tiktoken, encoding cl100k_base) на окна CHUNK_SIZE токенов с перекрытием CHUNK_OVERLAP; хвостовой чанк меньше CHUNK_MIN_TARGET сливается с предыдущим. Заметка ~20 000 символов ≈ 7 500 токенов ≈ ≤9 чанков; типичная короткая заметка — один чанк, схема вырождается в прежнюю. Зачем: вектор полного текста «размазывает» семантику — поиск по конкретному факту из середины длинной заметки проседает; чанк же несёт смысл своего участка, а лучший чанк заметки задаёт и её косинус релевантности, и snippet.

Как это устроено:

  • Хранение: тексты чанков — notes_chunks (FK на заметку, cascade при физическом удалении; soft delete чанки сохраняет — trash ищется как раньше), вектора чанков — notes_chunks_vec (vec0, cosine, та же модель и размерность, что у заметок).

  • Reuse: уместилась в один чанк ≤ CHUNK_SIZE — вектор чанка копируется из готового полного вектора, Ollama вызывается один раз.

  • Pending без статус-колонки: «вектор чанка готов» = есть строка в notes_chunks_vec (анти-джойн). Отказ векторизации или новый текст при update оставляют чанки pending — докодирует воркер.

  • Воркер: третья фоновая петля (рядом с до-векторизацией заметок и суммаризацией): вычитывает партию EMBEDDING_BATCH_SIZE × EMBEDDING_CONCURRENT_REQUESTS чанков (32 × 3), режет на подъёмки по 32, кодирует не более 3 запросов одновременно; отказ подъёмки не портит остальных (успешные записываются, отказавшие ждут back-off 30 с → ×2 → 15 мин). Гонка с memory_update закрыта: вектор пишется только на неизменённый с вычитки чанк.

  • Поиск: KNN по чанкам (топ-50) → агрегация до заметок: лучший чанк задаёт cosine и snippet (первые SNIPPET_CHARS символов чанка; поля полной сервисной/REST-выдачи — MCP их не отдаёт); заметки без готовых чанк-векторов (легаси, pending) ищутся по полному вектору, как раньше. FTS-плечо и RRF не менялись.

  • Пере-чанковка: смена CHUNK_SIZE/CHUNK_OVERLAP/CHUNK_MIN_TARGET (или модели/размерности) фиксируется meta-таблицей при старте: при смене чанковых параметров полного вектора это не касается (дропается только notes_chunks_vec), но все заметки (включая корзину) пере-чанковываются заново — короткие получают reuse сразу, остальные остаются pending до догонки воркером.

Read-таймаут векторизации — константа 720 с (решение 2026-08-30): 8B-модель на CPU-хосте кодирует полный 15k-текст ~2 мин, длинные тексты должны дорабатываться, а не рваться в retry (короткие — миллисекунды). Живая проверка механики — tests/test_integration_live.py (15k-заметка, работает живой Ollama, скип при её недоступности).

Эксплуатация

Логи. Весь stdout — JSON (docker compose logs -f second-brain): tool_call-события по всем 6 инструментам (tool, latency_ms, число результатов; поисковый запрос — первые 80 символов; тексты заметок в логи не пишутся), startup, backup_created/backup_failed, access/error uvicorn. Уровень — LOG_LEVEL.

Backup. Файлы notes-<UTC>.db в BACKUP_DIR (по умолчанию /data/backups, внутри volume ./data); первый — сразу после старта, далее раз в сутки; каталог держит BACKUP_KEEP свежайших. Восстановление — останови сервис, замени notes.db снапшотом (рядом -wal/-shm исходной БД тоже убери/учти), запусти снова. Копии читаются обычным sqlite3.

Прямой доступ оператора к БД (REQUIREMENTS §3): sqlite3 data/notes.db. Undo soft-delete — снять метку: UPDATE notes SET deleted_at = NULL WHERE id = ?; FTS-синхронизация сверится и починится сама на следующем старте.

Проверка MCP: curl-handshake из раздела о подключении; tools/list возвращает ровно 6 инструментов memory_*; без/с неверным токеном — 401.

Архитектура в двух словах

Один FastAPI-процесс: REST (/health, /notes, /search — для оператора)

  • MCP Streamable HTTP (/mcp) над одним service-слоем. SQLite (WAL): notes + FTS5 trigram + vec0 (вектор полного текста + вектора чанков). Векторизация и суммаризация — внешние Ollama; отказ любой не ломает CRUD (pending-статусы + фоновый воркер с back-off 30с→×2→15мин и деградация поиска до FTS-only). Подробности — архитектура, потоки §4.

Лицензия

Распространяется под лицензией MIT. Разрешено свободное использование, изменение и распространение, в том числе в коммерческих целях.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that provides semantic memory with search, related-content traversal, and write-back capabilities, all powered by local embeddings of your notes, documents, and chat histories.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Local-first memory server that stores notes, contacts, and future data as a unified entity graph, providing hybrid retrieval (vector + keyword) for AI assistants via MCP.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A personal note store exposed as an MCP server. Enables any MCP-speaking assistant to create, search, list, and categorize notes, with per-client bearer tokens for author attribution.
    168
    MIT

View all related MCP servers

Related MCP Connectors

  • Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.

  • Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.

  • Cross-vendor AI memory over MCP. One semantic store, readable and writeable from every MCP client.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/philadelfic/LLM-second-brain'

If you have feedback or need assistance with the MCP directory API, please join our Discord server