tolstoy-mcp
# tolstoy-mcp — память Толстого для Claude
Локальный MCP-сервер с поиском по 90-томному Полному собранию сочинений Л. Н. Толстого
(сочинения, дневники, записные книжки, письма), дневникам и воспоминаниям современников
(Гусев, Гольденвейзер, Маковицкий, С. А. Толстая) и примечаниям редакторов.
- `recall` — гибридный поиск фрагментов: по смыслу (bge-m3) и по словам (FTS5 со стеммингом), объединение через RRF;
- `read_document` — дочитать письмо, дневниковую запись или главу целиком или окно вокруг найденного фрагмента;
- промпт `tolstoy` — Claude говорит от лица Толстого, его орфографией, и ссылается на источники.
Всё работает локально, без API-ключей. При первом запуске скачивается около 800 МБ:
база текстов (≈200 МБ сжатая, 500 МБ на диске) и модель для запросов (≈590 МБ).
## Установка
**Claude Desktop.** Скачать `tolstoy-<версия>-<ОС>.mcpb` со страницы
[Releases](../../releases) и открыть его двойным щелчком (или «Настройки → Расширения → Установить
расширение»). Пакеты: `darwin` (Apple Silicon), `win32` (x64 и ARM), `linux` (x64 и ARM).
**Claude Code и другие MCP-клиенты** (нужен Node.js ≥ 22.13):
```bash
claude mcp add tolstoy -- npx -y tolstoy-mcp
npx -y tolstoy-mcp download # по желанию: скачать данные заранее, а не при первом вопросе
```
Пока данные скачиваются, инструменты отвечают, сколько осталось. Данные лежат в системном
каталоге данных приложения (`~/.local/share/tolstoy-mcp`, `~/Library/Application Support/tolstoy-mcp`,
`%LOCALAPPDATA%\tolstoy-mcp`); переопределить — переменной `TOLSTOY_DATA_DIR`.
```bash
npx tolstoy-mcp info # что скачано и где
npx tolstoy-mcp search "что Толстой писал Фету о Шопенгауэре" --top 5
npx tolstoy-mcp search "непротивление злу насилием" --mine # только тексты самого Толстого
```
## Как устроено
```
TEI/XML ──tei-importer──▶ PostgreSQL + pgvector ──tei-importer export──▶ export/*.jsonl.gz + chunks.f32
(репозиторий TEI, importer/: парсинг, чанки, векторы bge-m3) │
npm run build:db
▼
GitHub Release data-v1 ◀──────────────── tolstoy-v1.db.gz (SQLite: тексты, FTS5, int8-векторы)
│ первый запуск: скачать и проверить sha256
▼
Claude ◀──stdio──▶ tolstoy-mcp: bge-m3 (ONNX int8) векторизует запрос → перебор int8-векторов + FTS5 → RRF
```
- **SQLite** через встроенный `node:sqlite`: без нативных аддонов, поэтому работает и во встроенном
Node Claude Desktop (Electron), где аддоны под чужой ABI не грузятся.
- **Векторы** — int8 в обычной таблице (113 МБ вместо 450), поиск полным перебором в JS за ~125 мс.
sqlite-vec пробовали: без ANN-индекса он не быстрее, а нативную сборку тянет. Ранжирование int8 почти
не отличается от float32 (топ-10 совпадает на 9–10 из 10).
- **Полнотекстовый поиск** — FTS5 по основам слов: в SQLite нет русского стеммера, поэтому и текст, и запрос
заранее прогоняются через Snowball (`snowball-stemmers`).
- **Модель запросов** — [Xenova/bge-m3](https://huggingface.co/Xenova/bge-m3) (ONNX int8) через `onnxruntime-node`
и `@huggingface/tokenizers`; это та же BAAI/bge-m3, которой векторизован корпус (косинус с Python-версией 0,98).
## Разработка
```bash
npm ci --ignore-scripts # postinstall onnxruntime-node докачивает CUDA; нам нужен только CPU
npm test # vitest: юнит-тесты и MCP-сервер на мини-базе из test/fixture.ts
npm run lint && npm run typecheck
npm run build # tsup → dist/index.js
npm run dev -- search "Ясная Поляна"
```
Сквозной тест на настоящих данных (собранный `dist`, stdio): положить базу и модель в `.data/`
(`TOLSTOY_DATA_DIR=.data node dist/index.js download`) и запустить `TOLSTOY_E2E_DATA_DIR=.data npm test`.
### Новая версия данных
1. В репозитории TEI: `cd importer && uv run tei-importer export` (дамп в `importer/export/`).
2. Здесь: `npm run build:db -- <путь к export> --gzip` — соберёт `build/tolstoy-v1.db(.gz)` и впишет размер и sha256
в `data/assets.json`.
3. Выложить: `gh release create data-v1 build/tolstoy-v1.db.gz` (или `gh release upload data-v1 … --clobber`),
закоммитить `data/assets.json`. Если меняется схема, поднять `DB_FORMAT` в `src/schema.ts`:
имя файла станет `tolstoy-v2.db`, и старые установки не подхватят несовместимую базу.
### Релиз
`npm version patch && git push --follow-tags`. Workflow `release.yml` собирает `.mcpb` под каждую ОС,
проверяет каждый на своей платформе (`scripts/smoke.mjs`: нативный onnxruntime грузится, сервер отвечает
на `initialize` и `tools/list`), выкладывает их в GitHub Release и публикует пакет в npm
(trusted publishing: репозиторий и `release.yml` нужно один раз указать в настройках пакета на npmjs.com).
## Лицензия
Код — MIT. Тексты — корпус [«Весь Толстой в TEI/XML»](https://github.com/tolstoydigital/TEI)
проекта Tolstoy Digital, CC BY-SA. Модель BAAI/bge-m3 — MIT.
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: 'recall' performs hybrid search for fragments by topic, while 'read_document' sequentially reads a full document. An agent can easily tell them apart without overlap.
'read_document' follows a clear verb_noun pattern, but 'recall' is a bare verb without an object, deviating slightly. Both are lowercase and action-oriented, so the set is mostly consistent with minor variation.
Two tools are borderline thin for a corpus server; typical well-scoped sets have 3–15 tools. While search and read cover a basic retrieval loop, additional tools for discovery or metadata could be expected.
The surface allows searching and reading documents, but there is no explicit way to list or browse available documents, nor to retrieve metadata such as dates or titles. This creates a notable gap for agents that need to discover what exists before reading.