Типичный ИИ-агент, работающий с большой кодовой базой, ищет нужные символы через grep, glob или прямое чтение файлов. Каждый такой запрос тратит токены на передачу содержимого — и чем больше репозиторий, тем дороже обходится даже простой поиск функции по имени. Разработчик под ником Regsorm предложил альтернативу: держать структурный индекс кода в SQLite и давать агентам доступ к нему через MCP-протокол.

MCP (Model Context Protocol) — стандарт, который позволяет языковым моделям вызывать внешние инструменты и источники данных через унифицированный интерфейс. Вместо того чтобы читать файлы напрямую, агент отправляет запрос MCP-серверу, который возвращает уже готовый структурированный ответ. В случае code-index-mcp этим сервером выступает прослойка над SQLite-базой, где хранится разобранный код.

МетрикаСтарый подходНовый подход
Время инициализации на 93 000 файлах~163 секунды (SHA-256 по всем файлам)~4 секунды (сначала mtime + size, SHA только при изменении)
Размер WAL за сутки (13 папок)до 43 ГБ без контроляконтролируется через wal_checkpoint(TRUNCATE)
Размер WAL для одного репо19 ГБ при БД 4,7 ГБсбрасывается после каждой пачки записей

Парсинг выполняет tree-sitter — библиотека инкрементального синтаксического анализа, которую используют многие редакторы кода для подсветки синтаксиса и навигации. Она умеет разбирать десятки языков и строить синтаксическое дерево файла, из которого можно извлечь функции, классы и граф вызовов. Именно эти данные оседают в индексе, а не сырой текст файлов — хотя таблица file_contents с zstd-сжатием тоже есть для задач, где агенту нужен полный исходник.

Демон следит за изменениями файлов в реальном времени через file watcher — индекс обновляется без полного пересчёта.

Ключевая инженерная проблема — актуальность индекса. Если агент сам правит файлы, статичная база устаревает после первого же коммита. Решение — демон с file watcher, который отслеживает изменения в реальном времени и переиндексирует только затронутые файлы. На старте вместо полного пересчёта SHA-256 хэшей демон сначала сверяет mtime и размер файла: на корпусе из 93 000 файлов это сократило время инициализации с 163 до 4 секунд.

Архитектура намеренно асимметрична: демон — единственный писатель, MCP-серверы только читают. Это позволяет подключать к одному index.db несколько параллельных процессов без блокировок — например, несколько моделей одновременно работают с одним репозиторием. Supervisor поднимает по одному MCP-серверу на репо.

При долгой непрерывной работе обнаружилась неочевидная проблема SQLite в WAL-режиме: за сутки на стенде с 13 индексируемыми папками WAL-файлы разрослись до 43 ГБ. Для одного репозитория index.db-wal весил 19 ГБ при основной базе в 4,7 ГБ. Стандартный PRAGMA wal_autocheckpoint переносит страницы из WAL в основной файл, но физически не уменьшает WAL. Проблему решил PRAGMA wal_checkpoint(TRUNCATE) после каждой пачки записей.

Поверх индекса стоит кэширующий прокси mcp-cache-ci с трёхуровневой инвалидацией. Первый уровень — точечный сброс: когда демон переиндексирует файл, он отправляет POST /invalidate прокси, и тот удаляет все кэшированные ответы, построенные из этого файла. Второй уровень — зависимость ответа от конкретных файлов, которую прокси запоминает при выдаче. Третий — TTL на случай потери события.

Исходный проект вырос из задачи разобрать выгрузку конфигурации 1С с 43 расширениями и нулевой документацией. Специфика платформы потребовала отдельного модуля: bsl-indexer рекурсивно обходит дерево папок, находит все Configuration.xml на глубину до двух уровней и сводит объекты базы и расширений в одну таблицу через INSERT OR IGNORE. Универсальная часть выделена в отдельный code-index, не привязанный к 1С.

Автор честно отмечает главный практический минус: модели периодически «забывают» про индекс и возвращаются к grep и glob по мере заполнения контекстного окна — даже при явных инструкциях в системном промпте. Код опубликован на GitHub под именем code-index-mcp.