Skip to main content
Glama

selti — Semantic Memory MCP Server

selti — высокопроизводительный MCP-сервер семантической памяти для AI-агентов. Обеспечивает векторное хранение, поиск по семантической близости и интеллектуальную дедупликацию записей на основе протокола MCP (Model Context Protocol) через SSE-транспорт.


Примечание: Данный проект разработан с применением технологий искусственного интеллекта в рамках рабочего процесса Argenta Team. Код прошел рецензирование, тестирование и подготовлен к эксплуатации в production-среде.


Стек технологий

Компонент

Технология

Язык

Python 3.12

Фреймворк

FastAPI + FastMCP

База данных

PostgreSQL 17 + pgvector (HNSW)

Кеш

Redis 7

Мониторинг

Prometheus + Grafana

Контейнеризация

Docker + Docker Compose


Related MCP server: elephantasm-mcp

Архитектура

Система построена по многослойной архитектуре с чётким разделением ответственности:

Client (MCP over SSE)
       |
       v
   FastAPI / FastMCP ─── Auth Middleware (опционально)
       |
       v
   ┌─────────────────────────────────────────┐
   │            MCP Tools (16)               │
   │  store / search / get / update / delete │
   │  list / forget / ingest / stats / find  │
   │  recent / archive / link / unlink       │
   │  get_relations / traverse / graph_stats │
   └──────────────────────┬──────────────────┘
                          │
                          v
   ┌─────────────────────────────────────────┐
   │           MemoryService                 │
   │        (бизнес-логика)                  │
   └──────┬──────────────────────┬───────────┘
          │                      │
          v                      v
   ┌───────────┐        ┌───────────────┐
   │ DedupEngine│◄──────►│ Embedding API │
   │exact+sem. │        │  + Redis Cache│
   └─────┬─────┘        └───────┬───────┘
         │                      │
         v                      v
   ┌─────────────────────────────────────────┐
   │          MemoryRepository               │
   │       (SQL via asyncpg)                 │
   └──────────────────┬──────────────────────┘
                      │
                      v
   ┌─────────────────────────────────────────┐
   │    PostgreSQL 17 + pgvector (HNSW)      │
   │        4096-мерные эмбеддинги           │
   │        + Relations table (граф)         │
   └─────────────────────────────────────────┘

Слои архитектуры:

  • MCP Tools — 16 инструментов, декорированных FastMCP. Валидация namespace, трекинг метрик, обработка ошибок. Включают инструменты для графа знаний (link, unlink, get_relations, traverse, graph_stats).

  • DedupEngine — двухуровневая дедупликация: точная (SHA256) и семантическая (cosine distance). Оптимизирован: кеширует эмбеддинги в DedupDecision.

  • MemoryService — координатор бизнес-логики: вызов эмбеддингов, дедупликация, взаимодействие с репозиторием. Поддерживает batch-операции и Relations API.

  • Repository — уровень доступа к данным на asyncpg; сырые SQL-запросы с параметризацией. Включает методы для графа (add_relation, traverse, get_graph_stats) и archive.

  • PostgreSQL / pgvector — HNSW-индекс для 4096-мерных векторов, B-tree индексы для фильтрации, JSONB для метаданных. Таблица relations для графа знаний.

  • Redis Cache — кеш эмбеддингов (SHA256-ключи, TTL 24 часа); снижает нагрузку на Embedding API.


MCP Tools

Сервер предоставляет 16 инструментов для управления семантической памятью:

Основные инструменты

Tool

Описание

Параметры

memory_store

Сохранить запись с дедупликацией

content, user_id, metadata?, namespace?

memory_search

Векторный поиск по семантической близости

query, user_id, limit?, threshold?, namespace?

memory_get

Получить запись по идентификатору

id

memory_update

Обновить содержимое и/или метаданные записи

id, content?, metadata?

memory_delete

Удалить запись по идентификатору

id

memory_list

Список записей с фильтрацией и пагинацией

user_id?, namespace?, limit?, offset?

memory_forget

Массовое удаление всех записей пользователя

user_id, namespace?

memory_ingest_batch

Массовое сохранение набора записей с дедупликацией

entries: list[{content, metadata?, namespace?}], user_id

memory_stats

Статистика по неймспейсам: количество записей, дата обновления

user_id

memory_find_similar

Поиск семантически похожих записей без сохранения

content, user_id, limit?, threshold?, namespace?

memory_recent

Последние записи по времени создания

namespace?, limit?, since?

memory_archive

Мягкое удаление: установить is_archived = true

id

Инструменты для графа знаний

Tool

Описание

Параметры

memory_link

Добавить связь между гранулами

source_id, target_id, link_type?, description?, weight?

memory_unlink

Удалить связь между гранулами

source_id, target_id, link_type

memory_get_relations

Получить связи для гранулы

source_id, target_id?

memory_traverse

Обход графа от стартовой вершины

start_id, depth?, link_types?

memory_graph_stats

Статистика графа: количество связей, сирот, средние связи

Каждый инструмент инструментирован метриками: количество вызовов, длительность выполнения, статус (ok/error).


Namespace-стратегия

Namespace обеспечивают логическую изоляцию данных в рамках одной базы. Передаются опционально (по умолчанию — default). Валидация на уровне tools; неверное значение вызывает ValueError.

Namespace

Назначение

default

Общие записи

user_facts

Факты о пользователе

code_knowledge

Знания из кодовой базы

dialogue_insights

Инсайты из диалогов

project_meta

Метаданные проектов


Дедупликация

Ядро системы — DedupEngine, реализующий двухуровневую стратегию предотвращения дубликатов.

Уровень 1: Exact Match

Вычисляется SHA256(content). Выполняется поиск по content_hash в пределах namespace:

  • user_factsUPDATE (перезапись существующей записи)

  • остальныеSKIP (пропуск, возврат существующей записи)

Уровень 2: Semantic Match

Если точное совпадение не найдено, генерируется эмбеддинг и выполняется векторный поиск. При score >= threshold запись считается дубликатом → SKIP.

Пороги семантической дедупликации (per-namespace)

Namespace

Порог

default

0.95

user_facts

0.90

code_knowledge

0.95

dialogue_insights

0.85

project_meta

0.90

Пороги настраиваются через переменную DEDUP_THRESHOLDS. Полное отключение — DEDUP_ENABLED=false.


Быстрый старт

Предварительные требования

  • Docker 24+ и Docker Compose v2

  • Python 3.12 (для миграций вне контейнера)

Запуск

# 1. Клонировать репозиторий
git clone <repository-url>
cd selti

# 2. Скопировать шаблон окружения
cp .env.example .env

# 3. Сгенерировать пароли
python3 -c "import secrets; print(secrets.token_urlsafe(32))"

# 4. Заполнить .env:
#    PG_PASSWORD     — пароль суперпользователя PostgreSQL
#    APP_PASSWORD    — пароль пользователя приложения athena_app
#    REDIS_PASSWORD  — пароль Redis

# 5. Запустить с локальными PostgreSQL и Redis
docker compose --profile local-db up -d

# 6. Проверить здоровье сервера
curl http://localhost:8000/health

# 7. Применить миграции базы данных
python migrations/run.py

Для подключения к внешним PostgreSQL и Redis — запустите без профиля --profile local-db и укажите соответствующие URL в .env.


Celery Setup

Система использует Celery для асинхронной обработки тяжёлых операций: векторного поиска, batch-вставок, дедупликации и работы с эмбеддингами. MCP-сервер только ставит задачи в очередь, а воркеры выполняют всю работу.

Архитектура

MCP Server (FastMCP) ──send_task()──▶ Redis (broker) ──▶ Celery Worker (prefork)
                                                                    │
                                    ┌───────────────────────────────┤
                                    │               │               │
                                    ▼               ▼               ▼
                              PostgreSQL        Qdrant        Embedding API
                              (pgvector)       (векторы)      (эмбеддинги)

Почему Celery, а не asyncio в MCP-сервере: вся логика selti — async (asyncpg, httpx), но тяжёлые операции (embedding, векторный поиск) блокируют event loop. Celery prefork воркеры изолируют эти операции в отдельных процессах, не блокируя обработку MCP-запросов.

Очереди

Очередь

Назначение

Таймаут (soft/hard)

memory

store, search, get, update, delete, archive, link, unlink

240s / 300s

batch

ingest_batch

600s / 900s

hash

hash_upsert, hash_get, hash_list, hash_delete

120s / 180s

Запуск

# Development — всё вместе
docker compose up -d

# С Flower (мониторинг воркеров)
docker compose --profile dev up -d

# Только воркер (вручную, для отладки)
celery -A memory_server.celery_app worker \
    -Q memory,batch,hash \
    -c 4 \
    --without-gossip \
    --without-mingle \
    --without-heartbeat \
    -l INFO

# Только Flower
celery -A memory_server.celery_app flower --port=5555

Production-опции воркера

celery -A memory_server.celery_app worker \
    -Q memory,batch,hash \
    -c 4 \
    --without-gossip \
    --without-mingle \
    --without-heartbeat \
    --max-tasks-per-child=1000 \
    --max-memory-per-child=200000 \
    --logfile=- \
    -l INFO

Флаг

Зачем

--without-gossip

Экономит ~10% CPU, ускоряет старт

--without-mingle

Экономит ~10% CPU, не нужен в single-worker

--without-heartbeat

Экономит ~10% network

--max-tasks-per-child=1000

Реклайм памяти, защита от утечек

--max-memory-per-child=200000

OOM-защита (200 MB на процесс)

Retry-политика

Задачи автоматически повторяются при ошибках сети или БД:

  • Максимум попыток: 5

  • Стратегия: exponential backoff + jitter

  • Базовая задержка: 30 секунд

Validation-ошибки (ValueError, InvalidNamespace) не ретраятся — это баги данных, а не транзиентные сбои.

Мониторинг

Сервис

URL

Назначение

Health

GET /health

Статус сервера + Celery worker

Metrics

GET /metrics

Prometheus: 8 Celery + Redis + Qdrant метрик

Tasks API

GET /tasks

Активные задачи

Task info

GET /tasks/{task_id}

Статус конкретной задачи

Cancel

POST /tasks/{task_id}/cancel

Отмена задачи (revoke)

Flower

http://localhost:5555

Веб-интерфейс мониторинга (dev)

Troubleshooting

Проблема

Причина

Решение

ConnectionRefused к Redis

Redis не запущен

docker compose up -d redis

Task is stuck / Acknowledgement timed out

Воркер упал во время задачи

Проверьте логи: docker compose logs celery-worker

Worker terminated (SIGKILL)

OOM — процесс съел >200 MB

Увеличьте CELERY_WORKER_MAX_MEMORY_PER_CHILD или добавьте RAM

SoftTimeLimitExceeded

Задача выполняется дольше лимита

Увеличьте таймаут или оптимизируйте запрос

Retry and give up (5 попыток)

Транзиентная ошибка не прошла

Проверьте доступность PostgreSQL / Embedding API

Flower не видит воркеры

--without-gossip блокирует discovery

В dev-режиме уберите флаг; в production используйте celery inspect ping

Unknown task при inspect registered

Воркер не подключился к broker

Проверьте CELERY_BROKER_URL и доступность Redis


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

Переменные окружения

Переменная

Описание

По умолчанию

DATABASE_URL

PostgreSQL connection string (asyncpg)

postgresql+asyncpg://athena:athena@localhost:5432/selti

REDIS_URL

Redis connection string

redis://:@redis:6379/0

EMBEDDING_API_URL

URL API эмбеддингов (OpenAI-совместимый)

http://10.0.0.21:8080/v1

EMBEDDING_API_KEY

Ключ аутентификации API эмбеддингов

(пусто)

EMBEDDING_MODEL

Модель эмбеддингов

qwen3-embedding-8b

EMBEDDING_DIMENSION

Размерность эмбеддинга

8192

API_KEY

Ключ аутентификации MCP-сервера

(пусто — аутентификация отключена)

LOG_LEVEL

Уровень логирования

INFO

DEDUP_ENABLED

Включить дедупликацию

true

DEDUP_THRESHOLD

Глобальный порог семантической дедупликации

0.95

SEARCH_DEFAULT_LIMIT

Лимит результатов поиска по умолчанию

10

SEARCH_DEFAULT_THRESHOLD

Порог релевантности поиска по умолчанию

0.7

MCP_HOST

Хост сервера

0.0.0.0

MCP_PORT

Порт сервера

8000

CELERY_BROKER_URL

URL брокера сообщений (Redis)

redis://localhost:6379/0

CELERY_RESULT_BACKEND

URL хранилища результатов (Redis)

redis://localhost:6379/0

CELERY_WORKER_CONCURRENCY

Количество воркер-процессов

4

CELERY_WORKER_MAX_MEMORY_PER_CHILD

OOM-лимит на процесс (KB)

200000

CELERY_TASK_ROUTES

Маршрутизация задач по очередям (JSON)

{"memory_tasks.*":{"queue":"memory"},"hash_tasks.*":{"queue":"hash"}}

PG_USER

Пользователь PostgreSQL (локальный профиль)

athena

PG_PASSWORD

Пароль PostgreSQL (локальный профиль)

REDIS_PASSWORD

Пароль Redis (локальный профиль)

PostgreSQL (локальный профиль)

Для локального запуска используется образ pgvector/pgvector:pg17 с предварительно настроенным HNSW-индексом:

  • Расширение vector

  • Таблица memories с колонкой embedding vector(8192)

  • HNSW-индекс с параметрами m = 16, ef_construction = 200

  • B-tree индексы: user_id, namespace, created_at DESC

  • Триггер автообновления updated_at

  • Уникальный индекс на (namespace, content_hash) для точной дедупликации


Аутентификация

Опциональная защита на основе API-ключа. Включается установкой переменной API_KEY в .env.

Механизм:

  • HTTP-middleware проверяет заголовок Authorization: Bearer <API_KEY> для всех эндпоинтов

  • ASGI-middleware защищает /mcp (mount-приложение FastMCP)

  • Белый список (доступ без аутентификации): /health, /metrics

При пустом значении API_KEY доступ открыт.


Мониторинг

Метрики Prometheus

Эндпоинт /metrics предоставляет 13+ метрик:

Метрика

Тип

Описание

athena_http_requests_total

Counter

Количество HTTP-запросов (method, endpoint, status)

athena_http_request_duration_seconds

Histogram

Длительность HTTP-запросов

athena_db_pool_size

Gauge

Текущий размер пула соединений

athena_db_pool_available

Gauge

Доступные соединения в пуле

athena_embedding_duration_seconds

Histogram

Длительность вызова API эмбеддингов

athena_search_results_count

Histogram

Количество результатов поиска

selti_count

Gauge

Общее количество записей (по namespace)

athena_mcp_tool_calls_total

Counter

Вызовы MCP-инструментов (tool, status)

athena_mcp_tool_duration_seconds

Histogram

Длительность выполнения MCP-инструментов

athena_embedding_cache_hits_total

Counter

Попадания в кеш эмбеддингов

athena_embedding_cache_misses_total

Counter

Промахи кеша эмбеддингов

athena_dedup_skipped_total

Counter

Пропуски дедупликации (namespace, reason)

athena_dedup_inserted_total

Counter

Вставки после проверки дедупликации

Healthcheck

curl http://localhost:8000/health

Ответ содержит версию сервера и статусы проверок конфигурации.

Grafana Dashboard

Готовый dashboard для PostgreSQL + pgvector — monitoring/dashboards/postgres-pgvector.json.

Экспортёры

Для production-развёртывания предусмотрены экспортёры (включаются через -f monitoring/exporters/docker-compose.exporters.yml):

  • postgres-exporter (порт 9187) — метрики PostgreSQL

  • redis-exporter (порт 9121) — метрики Redis

Алерты

Правила алертинга — monitoring/alerts/prometheus-rules.yml:

  • Доступность PostgreSQL и Redis

  • Высокая загрузка соединений

  • Конфликты запросов на реплике

  • Долгие запросы (> 5 минут)

  • Отставание WAL-архивации

  • Отсутствие бэкапов

  • Отсутствие HNSW-индекса при > 10k записей

  • Высокое потребление памяти Redis

  • Высокий процент промахов кеша Redis


Миграции

Управление схемой базы данных — через встроенный migration runner.

# Применить все неприменённые миграции
python migrations/run.py

# Откатить последнюю миграцию
python migrations/run.py --down

Миграции находятся в migrations/ — версионированные SQL-файлы с up/down-секциями. Система отслеживает применённые миграции в таблице _migrations.

Доступные миграции:

Файл

Описание

001_initial.sql

Начальная схема: расширение vector, таблица memories, HNSW-индекс, триггеры, функция поиска

002_dedup.sql

Дедупликация: content_hash, source_type, source_location, version, is_archived, уникальный индекс

003_athene_memory.sql

Расширение: embedding cache, batch operations

004_infrastructure.sql

Инфраструктурные метрики и мониторинг

005_relations.sql

Таблица relations для графа знаний: связи между гранулами, индексы, каскадное удаление


Zero-downtime Deploy

Скрипт deploy.sh реализует стратегию rolling-обновления:

  1. Пулл нового образа из GHCR

  2. Запуск нового контейнера на временном порту

  3. Ожидание прохождения healthcheck

  4. Переключение трафика (через reverse proxy или прямой restart)

  5. Остановка и удаление старого контейнера


Тестирование

Проект покрыт модульными и интеграционными тестами (142+ теста).

# Установка зависимостей для тестов
pip install -r requirements.txt

# Запуск тестов
pytest tests/ -v

# С отчётом о покрытии
pytest tests/ --cov=memory_server -v

Разработка

Проект разработан в рамках Argenta Team — архитектура, разработка и сопровождение информационных систем.

Разработчик: Dek1m


Argenta Team — архитектура, разработка и сопровождение информационных систем.


Auto-deploy test: 2026-08-01T08:54:55Z

Related MCP Connectors

Related MCP Servers