Skip to main content
Glama

MAST — Monorepo AST Search Tool

MAST — это поисковый движок по коду, который работает либо как MCP-сервер (для ИИ-ассистентов), либо как автономный CLI. Он разбирает файлы TypeScript и JavaScript с помощью настоящего AST-парсера (tree-sitter), сохраняет полученный граф символов и фрагменты кода в SQLite и отвечает на запросы лексическим поиском BM25, объединённым с ранкером точных совпадений деклараций через Reciprocal Rank Fusion.

Основной принцип дизайна: возвращать ровно тот код, который нужен ассистенту, и ничего больше. Вместо чтения целых файлов MAST возвращает конкретную функцию, интерфейс или объявление типа, соответствующее запросу, — экономя токены, уменьшая шум в контексте и позволяя ИИ-инструментам навигировать по большим кодовым базам, не утопая в нерелевантном содержимом.


Содержание


Related MCP server: codeix

Зачем нужен MAST?

Когда ИИ-ассистенту нужно понять код, наивный подход — читать целые файлы. Это тратит токены (большая часть файла из 200 строк нерелевантна вопросу), раздувает контекстное окно и заставляет модель на каждом вызове отделять сигнал от шума.

MAST предлагает другой подход:

  • Разбиение на уровне AST — каждая функция, класс, интерфейс и псевдоним типа — это отдельный фрагмент. Ассистент получает точное объявление, которое ему нужно, а не файл, в котором оно находится.

  • Ранжированный поиск — BM25 (FTS5) обрабатывает запросы по ключевым словам и идентификаторам; ранкер точных совпадений деклараций («ранкер D») ловит запросы по точным именам символов, которые триграммный токенизатор BM25 может ранжировать непоследовательно. Оба объединяются через Reciprocal Rank Fusion, так что фрагмент, найденный обоими ранкерами, получает более высокий ранг, чем тот, который нашёл только один из них.

  • Структурные запросы — «кто вызывает эту функцию?», «что реализует этот интерфейс?», «что импортирует этот файл?» — получают ответы из заранее построенного графа символов, а не из grep по исходникам. Ответы мгновенны и структурно корректны.

  • JIT-обнаружение устаревания — при каждом чтении MAST проверяет, изменился ли файл на диске с момента последней индексации. Если изменился, файл прозрачно пере-парсится в фоне до возврата результата. Индекс никогда не устаревает без ведома ассистента.

  • Учёт токенов — каждый ответ инструмента включает _stats с количеством возвращённых токенов и контрафактической оценкой «сколько бы стоил наивный полный файл», что даёт конкретную меру эффективности с течением времени.


Требования

  • Node.js ≥ 22 (репозиторий фиксирует версию, с которой ведётся разработка, в .nvmrc)

  • Набор инструментов C++ для двух нативных модулей (better-sqlite3, tree-sitter). Предварительно собранные бинарники покрывают большинство платформ; когда ни один не соответствует ABI вашего Node, node-gyp собирает из исходников, и для этого нужны:

    • macOSxcode-select --install

    • Debian/Ubuntusudo apt install build-essential python3

    • Windows — установите рабочую нагрузку «Разработка классических приложений на C++» из Visual Studio Build Tools

Никаких сервисов, никаких API-ключей, никакой сети во время запросов. Всё — локальный SQLite.


Установка

Как dev-зависимость проекта, который вы хотите индексировать, — рекомендуется, потому что версия тогда фиксируется в вашем lockfile вместе со всем остальным:

pnpm add -D @spikedpunch/mast     # or: npm i -D / yarn add -D

Или глобально, если вам нужен один mast для множества копий репозиториев:

pnpm add -g @spikedpunch/mast

Проверка:

mast --version

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

Три команды от нуля до поискового индекса:

cd /path/to/your/project

mast init                    # write .mast/, then run the first full index
mast status                  # confirm it is fresh
mast search "createUser"     # search it

mast search выводит соответствующее объявление, а не файл, в котором оно находится:

$ mast search "compareVersions" -n 1
src/cli/upgrade-cmd.ts:39  compareVersions  function  (exported)
    /** Semver compare, prerelease-aware. Returns <0, 0, or >0. */
    export function compareVersions(a: string, b: string): number {
      ...
    }

270 tokens returned vs 2140 to read the files whole — 87% saved

Последняя строка — это реальный учёт, а не лозунг: каждый ответ несёт _stats с тем, что было возвращено, и верхнюю границу стоимости чтения указанных файлов целиком. Для маленького файла экономия может быть отрицательной, и MAST честно это говорит, а не округляет в свою пользу.

Ответ, за который MAST не может поручиться полностью, говорит об этом на той же поверхности, где показывает результат. Файл, изменённый после индексации, помечается, потому что тело, напечатанное под ним, — старое:

! 1 of 2 results are from files that changed since indexing —
  the code shown below may be out of date. Run `mast index` to refresh.

src/a.ts:1  alphaFunction  function  (exported)  [STALE]

А пустой ответ различает две причины, по которым он может быть пустым:

$ mast search "kept_symbol"
no matches (mast indexes TypeScript, JavaScript, and Markdown only —
a symbol in any other language is invisible to it, not absent from the repo)

$ mast search "anything"          # in a directory with no index
nothing is indexed at this path — this is not evidence the symbol is absent.
run `mast index` first, or check `mast status` for the path being used.

Сузьте запрос с помощью --type, --language, --exported, --file, -n:

mast search "greet" --type method --exported -n 5
mast search "config" --file "src/store/**"

Поддерживайте актуальность по мере работы — или позвольте git-хуку делать это:

mast index --incremental     # reindex only what changed
mast install-hooks           # reindex automatically after commits and checkouts

Всё, что поставляется с вашей сборкой, читается офлайн, так что вам никогда не придётся выяснять, какие документы соответствуют вашей версии:

mast docs                    # list the topics
mast docs spec               # the full behavioural specification
mast skill                   # the instructions to paste into an agent prompt

Использование из ИИ-ассистента

MAST говорит на MCP через stdio. mast serve — команда сервера; конфигурация ниже отличается только тем, где каждый инструмент хранит свой файл конфигурации.

Если вы установили MAST как dev-зависимость, а не глобально, замените mast на npx @spikedpunch/mast (или pnpm exec mast) в любом из этих примеров.

Claude Code

claude mcp add mast -- mast serve

Добавьте --scope project, чтобы записать .mcp.json в репозиторий, и ваша команда подхватит его из копии репозитория.

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json на macOS, %APPDATA%\Claude\claude_desktop_config.json на Windows:

{
  "mcpServers": {
    "mast": {
      "command": "mast",
      "args": ["serve"],
      "env": { "MAST_STATE_DIR": "/absolute/path/to/your/project/.mast" }
    }
  }
}

Claude Desktop не запускается в каталоге вашего проекта, поэтому MAST_STATE_DIR должен быть абсолютным. CLI и интеграции с редакторами ниже выводят его из рабочего каталога.

Cursor

.cursor/mcp.json в проекте или ~/.cursor/mcp.json глобально:

{
  "mcpServers": {
    "mast": { "command": "mast", "args": ["serve"] }
  }
}

VS Code (GitHub Copilot)

.vscode/mcp.json:

{
  "servers": {
    "mast": { "type": "stdio", "command": "mast", "args": ["serve"] }
  }
}

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "mast": { "command": "mast", "args": ["serve"] }
  }
}

Zed

settings.json:

{
  "context_servers": {
    "mast": { "command": { "path": "mast", "args": ["serve"] } }
  }
}

Любой другой MCP-клиент

Запустите mast serve через stdio из корня проекта. Он объявляет одиннадцать инструментов чтения и не требует аргументов, кроме serve.

Расскажите ассистенту, как им пользоваться

Регистрация сервера даёт модели инструменты; она не говорит ей, когда их использовать или как читать помеченный ответ. mast skill выводит инструкции, написанные для этого, — вставьте их в свой системный промпт, CLAUDE.md, .cursorrules или файл навыка:

mast skill                    # print it
mast skill --install          # splice it into this project's agent config files
mast skill --install --dry-run

--install записывает только в файлы, которые уже существуютCLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md — и пишет внутри помеченного блока, так что повторный запуск после обновления заменяет предыдущую копию, а не добавляет вторую. Он никогда не запускается сам по себе и никогда не создаёт файл конфигурации, который вы не хранили раньше.


Обновление

mast upgrade

Эта команда проверяет наличие более новой версии и выводит точную команду для того, как вы установили MAST, — она не обновляет на месте, потому что CLI не может надёжно отличить глобальную установку от dev-зависимости, а ошибка в догадке запустит не ту команду в вашем репозитории.

Что важнее, она сообщает то, чего ваш пакетный менеджер не может: меняет ли обновление схему индекса. Когда меняет, MAST отбрасывает индекс и перестраивает его при следующем serve или index. Ничего не теряется, что нельзя перестроить, — индекс — это производное состояние, — но для большого монорепозитория это минуты, и лучше знать об этом заранее, чем обнаружить как необъяснимую остановку.


Использование MAST в монорепозитории

Один индекс в корне репозитория обычно правильный. Межпакетные импорты разрешаются, так что mast_callers находит вызывающих в соседних пакетах — это и есть причина использовать инструмент для монорепозитория, а не один индекс на пакет.

Что индексируется. .ts, .tsx, .js, .jsx и .md, за вычетом node_modules, dist, build, coverage, .next, .turbo, .mast и тестовых файлов. Переопределите с помощью --extensions и --exclude в mast init или отредактируйте .mast/config.json.

Другие языки не индексируются, и это важно. MAST разбирает только TypeScript и JavaScript. Символ, определённый на Python, Go, Java или Rust, отсутствует в индексе, что выглядит ровно как отсутствие в репозитории. Относитесь к пустому результату как к «MAST не нашёл это», а не как к «этого не существует» — mast skill говорит это и модели.

Добавьте .mast/ в .gitignore. Это производное состояние, оно большое и машино-специфично.

Пользовательское расположение индекса не запоминается между запусками. --state-dir применяется только к той команде, которой вы его передали. Путевые настройки намеренно никогда не считываются обратно из сохранённой конфигурации — абсолютный путь, записанный предыдущим запуском (или предыдущим контейнером), может указывать туда, где больше ничего нет, или, что хуже, туда, что принадлежит другому проекту. Чтобы закрепить пользовательское расположение, поместите его в систему контроля версий или в окружение:

// mast.config.json, at the project root
{ "state_dir": ".cache/mast" }
export MAST_STATE_DIR=/absolute/path/to/index

Порядок разрешения: --state-dirMAST_STATE_DIRmast.config.json.mast. mast status выводит разрешённый каталог и прямо говорит, когда там ничего не индексировано.

Масштаб. Холодная индексация VS Code — 8 653 файла, 152 969 фрагментов — занимает около двух минут и создаёт каталог состояния размером 794 МБ. Инкрементальная переиндексация изменённого файла занимает миллисекунды.

Справочник CLI

mast init [path]

Инициализирует MAST для проекта и выполняет первоначальную полную индексацию.

Options:
  --state-dir <dir>        Where to write index state (default: <path>/.mast)
  --extensions <ext,...>   File extensions to index (default: .ts,.tsx,.js,.jsx,.md)
  --exclude <pattern,...>  Glob patterns to exclude
  --no-index               Create config only; skip initial indexing

Зачем: Создаёт структуру каталога состояния, записывает config.json и выполняет полный проход разбора + извлечения символов. Один запуск заранее означает, что последующие инкрементальные запуски будут обрабатывать только изменённые файлы.


mast search <query> [path]

Ищет в индексе и выводит читаемые результаты.

Options:
  -n, --limit <n>        Max results, 1-50 (default: 10)
  -t, --type <kind>      function | method | class_shell | interface | type | export | block | doc
  -l, --language <lang>  typescript | javascript | markdown
  -e, --exported         Only exported symbols
  -f, --file <glob>      Restrict to files matching a glob
      --state-dir <dir>  State directory
      --json             Emit the raw MCP response instead of text

Зачем: самый быстрый способ проверить, что на самом деле содержит индекс, и тот же путь кода, который использует MCP-инструмент mast_search, — он диспетчеризуется через зарегистрированный обработчик, а не перереализует ранжирование, поэтому результаты CLI и ассистента не могут разойтись. Флаги устаревания и усечения выводятся над результатами; пустой результат, который пуст потому, что индекс был занят, говорит об этом.

Для скриптов mast query mast_search '{...}' даёт побайтно идентичный MCP-вывод.


mast index [path]

Строит или обновляет индекс.

Options:
  --state-dir <dir>    State directory
  --incremental        Only reindex files changed since last run
  --show-progress      Print indexing progress to stderr
  --checker            Opt-in TypeScript-checker pass: upgrades heuristic potential_matches
                        into verified caller edges (or drops non-call-site noise). Can take
                        tens of seconds on a large monorepo — not part of the default path.

Почему инкрементально: Инкрементальный путь сравнивает текущий манифест файлов с сохранёнными mtime. Обрабатываются только устаревшие, добавленные или удалённые файлы — для большой кодовой базы это сокращает время индексации с секунд до миллисекунд в большинстве запусков.


mast serve

Запускает MCP-сервер через stdio.

Options:
  --state-dir <dir>         State directory
  --no-startup-reindex      Skip the startup staleness check (not recommended)
  --watch                   Watch source files and incrementally reindex on change
                             (interactive use; not needed in the container ladder)

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


mast status [path]

Выводит состояние индекса.

Options:
  --state-dir <dir>    State directory
  --json               Output as JSON

Сообщает last_indexed, indexed_files, chunk_count, stale_files, parse_errors, write_errors, index_fresh и freshness_cause. Используйте это для диагностики, почему результаты поиска выглядят устаревшими.


mast metrics [path]

Показывает метрики эффективности токенов.

Options:
  --since <window>        Time window: 7d, 24h, 30m (default: 7d)
  --rollup                Collapse raw rows older than --keep-days into daily roll-ups
  --vacuum                Delete daily roll-up rows older than --keep-days
  --keep-days <n>         Retention days (default: 7 for rollup, 90 for vacuum)
  --state-dir <dir>       State directory

Выводит таблицу с выравниванием по колонкам: имя инструмента, количество вызовов, возвращённые токены, средняя длительность и коэффициент эффективности. Периодически используйте --rollup + --vacuum, чтобы база данных метрик не росла бесконечно.


mast install-hooks [path]

Устанавливает git-хуки post-commit / post-checkout, которые автоматически запускают mast index --incremental, чтобы индекс оставался свежим между коммитами и переключениями веток без ручного шага.


mast query <tool> [json] [path]

Вызывает любой MCP-инструмент чтения напрямую, с побайтно идентичным MCP-транспорту выводом.

Options:
  --state-dir <dir>   State directory
  --json              Emit the exact single-line MCP response (default pretty-prints)
mast query mast_callers '{"symbol":"resolveConfig"}'
mast query mast_project_skeleton '{}'

Зачем: поверхность для скриптов и отладки. mast search — читаемая парадная дверь к одному инструменту; эта команда достигает всех одиннадцати и возвращает ровно то, что получил бы ассистент, — так что расхождение между тем, что видите вы, и тем, что видела модель, невозможно. Указание несуществующего инструмента выводит список существующих.


mast docs [topic]

Выводит документацию, поставляемую с установленной сборкой, — readme, spec или skill. Без аргументов перечисляет темы с версиями, к которым они относятся.

Зачем: устраняет шаг, на котором читатель ищет свою версию, а затем находит документацию для другой. Что выводит mast docs, то и делает бинарник в вашем node_modules.


mast skill [path]

Распечатайте инструкции MAST для вставки в системный промпт агента, CLAUDE.md, .cursorrules или файл навыка.

Options:
  --install    Splice into this project's existing agent config files
  --dry-run    With --install, report what would change without writing

Зачем: регистрация MCP-сервера даёт модели инструменты, но не суждение — когда искать, а не читать, что код-токены в запросе лучше прозы, и как читать флаг устаревания или усечения. Это также сообщает модели, что пустой результат означает «MAST не нашёл», а не «этого не существует», что является самым важным, что нужно понять о поисковом инструменте.


mast upgrade [path]

Проверяет наличие новой версии; выводит, как её установить и сколько это будет стоить.

Зачем: он определяет, как был установлен MAST, и выводит соответствующую команду, а не выполняет её, потому что CLI не может надёжно отличить глобальную установку от зависимости разработки. Он также сообщает, приводит ли обновление к изменению схемы индекса — что вынуждает выполнить полную переиндексацию при следующем serve, — и ваш пакетный менеджер не может вам этого сказать.


Справочник инструментов MCP

MAST регистрирует 11 инструментов на MCP-сервере. Каждый инструмент чтения включает блок _stats:

{
  tool: string,
  tokens_returned: number,
  tokens_full_file_upper_bound: number,
  files_referenced: string[],
  efficiency_ratio: number,           // 1 - (returned / full_file)
  duration_ms: number,
}

Лексический поиск BM25 + точное совпадение объявлений по индексированной кодовой базе.

{
  query:         string,              // natural language or identifier
  limit?:        number,              // max results (default 10, max 50)
  language?:     "typescript" | "javascript" | "markdown" | null,
  file_pattern?: string | null,       // glob: "src/api/**"
  chunk_type?:   "function" | "method" | "class_shell" | "interface" | "type" | "export" | "block" | "doc" | null,
  only_exported?: boolean
}

Возвращает: { results[], suggestions?, _stats }. Каждый результат включает file_path, start_line, end_line, content, chunk_type, symbol_name, parent_symbol, is_exported, match_score (оценка BM25, отрицательная; null, когда совпадение получено только от ранжировщика D), rank, match_snippet и необязательную подсказку related, когда метод и его класс-оболочка совпали (возвращается только результат с более высоким рейтингом). suggestions присутствует, возможно пустой, только когда results пуст — это подсказка «вы имели в виду» при нулевом результате.

Зачем: grep и glob находят точные строки и требуют, чтобы вызывающий уже знал шаблон. mast_search ранжирует по релевантности, объединяя два сигнала с помощью рангового слияния по обратной частоте:

  • BM25 (FTS5, токенизация триграммами) — универсальный лексический ранжировщик; обрабатывает ключевые слова и совпадения по подтокенам/в стиле camelCase.

  • Ранжировщик D (точное совпадение объявлений) — прямое совпадение с собственным symbol_name чанка (полное имя или последний сегмент через точку, без учёта регистра). Ловит точные запросы символов, которые триграммная оценка BM25 может занижать. Управляется ключом конфигурации declaration_exact_ranker (по умолчанию включён); когда он выключен, mast_search работает только на BM25.

Чанк, по которому согласованы оба ранжировщика, превосходит тот, который нашёл только один из них. file_pattern и language ограничивают пул, из которого черпают оба ранжировщика, поэтому ограниченный поиск никогда не вернёт файл вне области видимости. file_pattern — это глоб, сопоставляемый тем же примитивом, который применяет exclude_patterns во время индексации: * не пересекает /, ** пересекает, ? — один символ, не являющийся /, сопоставление чувствительно к регистру, а всё остальное — ., _, - — литерально.


mast_project_skeleton

Все экспортируемые символы, сгруппированные по файлам, опционально ограниченные каталогом.

{
  directory?:    string | null,       // path prefix: "src/api"
  max_depth?:    number,              // max subdirectory depth (default unlimited)
  file_pattern?: string | null        // glob filter on file paths
}

Возвращает: { files: [{ file_path, exports: string[] }], _stats }.

Зачем: перед навигацией по кодовой базе ассистенту нужна ориентация — «что здесь есть?». Читать каждый файл, чтобы найти его экспорты, расточительно. mast_project_skeleton возвращает карту «файл → экспортируемые имена» в пределах каталога за один вызов, позволяя ассистенту составить мысленную модель подсистемы, не открывая ни одного файла.


mast_exports

Все экспортируемые символы из одного файла с сигнатурами типов и TSDoc.

{
  file_path: string                   // relative to project root
}

Возвращает: { file_path, exports: [{ name, kind, signature, line, doc }], _stats }.

Зачем: это естественное продолжение mast_project_skeleton. Как только ассистент узнал, какой файл релевантен, mast_exports даёт полные сигнатуры без тел функций — достаточно, чтобы понять публичный интерфейс модуля, не платя за реализацию.

Методы намеренно опущены (они появляются через mast_signature для родительского класса), поэтому результат остаётся сфокусированным на публичном контракте модуля.


mast_signature

Объявление, TSDoc и разрешённый контекст типов параметров для именованного символа.

{
  symbol:     string,                 // e.g. "handleLogin", "AuthService"
  file_path?: string | null           // narrow to a specific file
}

Возвращает: массив SignatureResult, каждый с symbol, file_path, line, signature, doc, params, return_type и type_context.

type_context заполняется автоматически: определённые пользователем имена типов в PascalCase, встречающиеся в сигнатуре, разрешаются в их собственные сигнатуры через трёхприоритетный поиск — сначала тот же файл, затем именованные импорты, затем глобальный запасной вариант экспортируемых типов. Длинные сигнатуры обрезаются до 500 символов. Это означает, что один вызов mast_signature даёт ассистенту полную картину типов для функции без необходимости отдельных запросов.

Зачем: когда ассистент видит function processOrder(order: Order, ctx: RequestContext): Promise<Result>, знание сигнатур Order, RequestContext и Result необходимо для понимания того, что делает функция. Вместо трёх дополнительных вызовов инструментов mast_signature разрешает их встроенно.


mast_callers

Кто вызывает данный символ, с разделением на подтверждённых вызывающих (из графа символов) и потенциальные совпадения (из полнотекстового поиска по идентификаторам).

{
  symbol:              string,
  file_path?:          string | null,
  transitive?:         boolean,       // walk the full call chain (default false)
  include_potential?:  boolean        // include identifier_fts matches (default true)
}

Возвращает: { verified_callers[], potential_matches[], summary: { verified_count, potential_count, transitive, checker_classified_non_call_site, checker_classified_different_declaration }, _stats }.

Зачем: анализ влияния перед рефакторингом требует знания, кто зависит от символа. Подтверждённые вызывающие разрешаются через граф (окончательно, без ложных срабатываний из-за коллизий имён). Потенциальные совпадения — это совпадения по полнотекстовому поиску идентификаторов, где вызов не удалось статически разрешить; они могут быть ложными срабатываниями, но их стоит проверить. Разделение этих двух категорий позволяет ассистенту рассуждать об уверенности: если verified_count равен 3, а potential_count — 0, объём рефакторинга хорошо понятен. Если potential_count равен 15, неопределённость выше. Запуск mast index --checker повышает некоторые потенциальные совпадения до подтверждённых рёбер (или отбрасывает шум, не являющийся местами вызовов) — счётчики checker_classified_* сообщают, сколько именно, и равны 0, если проход проверки никогда не запускался.


mast_dependencies

Все импорты, записанные для файла.

{
  file_path: string
}

Возвращает: { file_path, imports: [{ module, symbols[], is_external, resolved_path? }], _stats }.

Зачем: понимание поверхности зависимостей файла — первый шаг к рассуждению о том, что он делает. Внешние импорты (без resolved_path) помечаются, чтобы ассистент знал границу разрешения. Внутренние импорты включают разрешённый путь, чтобы вызывающие могли проследить цепочку.


mast_implementors

Все конкретные классы, реализующие данный интерфейс, со списками их методов.

{
  interface_name: string
}

Возвращает: { results: [{ class_name, file_path, line, methods[] }], _stats }.

Зачем: в кодовой базе с внедрением зависимостей ответ на вопрос «что здесь на самом деле выполняется?» — это interface_name → implementors. Вместо поиска по implements InterfaceName MAST хранит явные рёбра IMPLEMENTS в графе во время индексации, что делает поиск мгновенным и структурно корректным.


mast_rename_impact

Составной чек-лист рефакторинга для переименования символа: места объявлений, подтверждённые вызывающие, потенциальные совпадения и реэкспорты из баррелей — одним вызовом.

{
  symbol:     string,
  file_path?: string | null
}

Возвращает: { symbol, declaration_sites[], verified_callers[], potential_matches[], barrel_exports[], summary: { declaration_count, verified_count, potential_count, barrel_count, checklist, checker_classified_non_call_site, checker_classified_different_declaration }, _stats }.

Зачем: переименование затрагивает не только места вызовов — реэкспорты из баррелей (export { Foo } from './foo', возможно, с псевдонимом) также нужно обновить, и их легко пропустить при простом поиске вызывающих. mast_rename_impact объединяет механику mast_callers с обнаружением баррельных реэкспортов, так что ассистент получает один чек-лист вместо трёх отдельных запросов.


mast_reindex

Запускает синхронную переиндексацию из MCP-сеанса.

{
  full?: boolean                      // force full reindex (default: incremental)
}

Возвращает: { files_indexed, files_skipped, chunks_added, chunks_removed, parse_errors, write_errors, duration_ms }.

Зачем: длительные сеансы редактирования накапливают устаревание — новые символы и файлы не будут найдены mast_search, пока они не проиндексированы (JIT-обработка устаревания сохраняет корректность координат строк уже проиндексированных файлов при чтении, но не может обнаружить совершенно новый файл или символ). mast_reindex позволяет ассистенту обновить индекс по требованию — например, после крупного рефакторинга — не выходя из MCP-сеанса. Флаг full доступен, если есть подозрение на повреждение инкрементального состояния.


mast_status

Снимок состояния индекса.

// no inputs

Возвращает: { state_dir, last_indexed, indexed_files, chunk_count, stale_files, parse_errors, write_errors, index_fresh, freshness_cause, seed_commit? }.

index_fresh равен true, только когда stale_files = 0 и индекс запускался хотя бы раз. freshness_cause равен "phase1_stale", когда остаются устаревшие файлы, и null, когда всё свежо. stale_files подсчитывает изменённые файлы, файлы на диске, которых вообще нет в индексе, и проиндексированные файлы, которые исчезли с диска, — то же число, которое сообщает mast status, из того же источника.

Зачем: перед длительным агентным рабочим процессом, зависящим от точной навигации по коду, ассистент может вызвать mast_status, чтобы подтвердить свежесть индекса или, если это не так, сообщить пользователю количество устаревших файлов.


mast_efficiency

Отчёт об экономии токенов за текущий сеанс или за всё время.

{
  scope:          "session" | "global",
  since_minutes?: number              // global scope: restrict to last N minutes
}

Возвращает: { scope, window_started_at, tokens_returned, tokens_full_file_upper_bound, efficiency_ratio, calls_total, calls_by_tool, tokenizer, counterfactual }.

Поле counterfactual — это читаемое предложение: «С наивным чтением полных файлов это стоило бы ~14 200 токенов; сэкономлено ~11 400 токенов (80,3%).»

Зачем: эффективность токенов — это вся причина существования MAST, но без измерения это просто утверждение. Каждый вызов инструмента асинхронно записывает возвращённые токены в metrics (отправил и забыл, < 1 мс). mast_efficiency агрегирует эти записи, чтобы ценность точной навигации по коду была конкретной и проверяемой.


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

MAST читает конфигурацию из mast.config.json в корне проекта, переменных окружения или флагов CLI. Приоритет (от высшего к низшему): флаг CLI → переменная окружения MAST_STATE_DIRmast.config.json → встроенные значения по умолчанию.

Ключ

По умолчанию

Описание

state_dir

.mast

Каталог для всего состояния индекса (относительно корня проекта)

file_extensions

.ts,.tsx,.js,.jsx,.md

Расширения исходных файлов для индексации

exclude_patterns

node_modules/**, dist/**, coverage/**, .kluster/**, **/*.test.ts, **/*.spec.ts

Glob-шаблоны для пропуска

rrf_k

60

Константа Reciprocal Rank Fusion (выше = более плоское ранжирование)

declaration_exact_ranker

true

Включить рангер D (точное совпадение объявления) в mast_search. Установите false, чтобы вернуть ранжирование только на BM25 без изменения кода.

chunk_split_threshold

100

Количество строк, выше которого объявление разбивается на перекрывающиеся подчанки

context_lines

3

Строки исходного кода до/после границ AST, включаемые в сохранённое содержимое

markdown_heading_depth

2

Максимальный уровень ATX-заголовка (##), который начинает новый чанк markdown-документа

Пример mast.config.json:

{
  "state_dir": ".mast",
  "exclude_patterns": ["node_modules/**", "dist/**", "**/*.test.ts"],
  "declaration_exact_ranker": true,
  "context_lines": 5
}

MAST_STATE_DIR — переопределяет каталог состояния без изменения mast.config.json. Полезно в CI или Docker-средах, где корень проекта доступен только для чтения.


Как это работает

Индексация

runIndex обходит проект с помощью fast-glob, вычисляет манифест на основе mtime и сравнивает его с сохранённым манифестом, чтобы найти устаревшие, добавленные и удалённые файлы. Для каждого файла, требующего обработки:

  1. Разборtree-sitter разбирает файл в конкретное синтаксическое дерево. Грамматика TypeScript используется для .ts и .tsx; грамматика JavaScript — для .js и .jsx. Markdown-файлы разбиваются на чанки по заголовкам (markdown_heading_depth), а не разбираются с помощью tree-sitter.

  2. Чанкинг — экстрактор разлагает CST на типизированные чанки: function, class_shell (объявление класса плюс сигнатуры членов, без тел), method (отдельные методы), interface, type, export, block и doc (разделы markdown). Классы всегда разлагаются так, чтобы поиск отдельного метода не возвращал всё тело класса.

  3. Подчанки — объявления длиннее chunk_split_threshold строк разбиваются на перекрывающиеся сегменты, чтобы ни один чанк не был слишком большим для полезного самодостаточного результата поиска.

  4. Граф символов — символы, импорты и рёбра (IMPLEMENTS, PARENT_OF, POTENTIAL_CALL) записываются в SQLite. Стратегия двухпроходной записи (сначала все файлы, затем рёбра) гарантирует, что рёбра могут ссылаться на символы, определённые в файле, разобранном позже в том же запуске.

  5. FTS — содержимое чанков записывается в виртуальную таблицу FTS5 с триграммным токенизатором, что обеспечивает поиск по подтокенам и camelCase. Таблица identifier_fts с токенизатором unicode61 обрабатывает точные поиски идентификаторов для потенциальных совпадений mast_callers.

Индексация — это единая фаза: чанки/граф/FTS обновляются вместе за один проход runIndex; отдельного этапа эмбеддингов нет.

Ранжированный поиск (BM25 + рангер D через RRF)

Запрос проходит через два рангера:

BM25 (FTS5): Запрос сопоставляется с chunk_fts с использованием встроенного ранжирования BM25 в SQLite, поверх триграммного токенизатора. Фильтры по шаблону файла и языку передаются в этот запрос как SQL-предикаты против таблицы files (не как предикаты FTS MATCH, потому что LIKE в SQLite FTS5 по непроиндексированным столбцам ненадёжен с MATCH). Оценки BM25 в SQLite отрицательные — более отрицательное значение означает более сильное совпадение; match_score в mast_search сохраняет этот знак.

Рангер D (точное объявление): Прямой SQL-предикат против chunks.symbol_name — совпадение полного имени или последнего сегмента после точки, без учёта регистра, с детерминированным порядком. Управляется ключом конфигурации declaration_exact_ranker (по умолчанию включён).

RRF-слияние: Два ранжированных списка объединяются с помощью Reciprocal Rank Fusion:

score(chunk) = Σ 1 / (k + rank(chunk))

с значением по умолчанию k = 60. Чанк, появляющийся на ранге 1 в обоих списках, получает вдвое больше очков, чем чанк, появляющийся только в одном. Чанки, появляющиеся только в одном списке, всё равно получают хорошие очки — ни один сигнал не доминирует.

JIT-проверки устаревания

Каждый инструмент чтения (search, exports, signature, callers, dependencies, implementors) вызывает jitRefreshFile перед возвратом результатов. Эта функция:

  1. Читает сохранённое mtime файла из таблицы files.

  2. Вызывает stat() для файла на диске.

  3. Если mtime на диске новее, захватывает structure.lock и немедленно переразбирает файл.

Это означает, что ассистент, редактирующий файл и сразу запрашивающий его, всегда увидит текущую версию, не дожидаясь плановой переиндексации. (JIT-устаревание обрабатывает файлы, уже известные индексу; совершенно новый файл или символ всё ещё требует mast_reindex или следующей плановой/наблюдаемой переиндексации, чтобы стать обнаружимым.)

Стартовая лестница

mast serve начинает принимать MCP-соединения менее чем за 1 секунду через четырёхступенчатую лестницу:

Step 1  Bootstrap state directory; copy Docker seed layer if present;
        best-effort remove orphaned pre-vector-store state              < 500ms
Step 2  Schema version check; open SQLite                               < 1s
Step 3  Register all 11 MCP tools; open stdio transport                 < 500ms
Step 4  Background incremental reindex                                  async

Все инструменты готовы к работе сразу после завершения шага 3 — нет окна запуска с ограниченной функциональностью. Когда предварительно собранный seed-индекс доступен в /opt/mast-seed, он копируется в каталог состояния на шаге 1 — фоновая переиндексация на шаге 4 затем обрабатывает только файлы, изменённые с момента сборки seed.

Модель конкурентности

Один advisory lock координирует параллельных писателей:

  • structure.lock — удерживается runIndex и JIT-переразборами. Предотвращает одновременное изменение графа SQLite двумя писателями.

Блокировка использует proper-lockfile (POSIX advisory locks через файл-маркер .lock). Таймаут устаревшей блокировки в 10 секунд предотвращает блокировку системы упавшим процессом. Инструменты чтения никогда не захватывают блокировку записи — они могут видеть кратковременно несогласованное состояние во время параллельной переиндексации и в этом случае возвращают file_busy_returning_stale_cache: true.

Структура хранения

.mast/
  graph.db              SQLite — symbols, edges, imports, chunks, FTS5 tables, metrics
  file_manifest.json    mtime snapshot from the last index run
  index.json            schema version, file count, chunk count, last_indexed
  config.json           resolved config written at init/serve time
  structure              lock marker (proper-lockfile target)

Эффективность токенов

Каждый вызов инструмента асинхронно записывает количество токенов в metrics. Запись включает:

  • tokens_returned — фактические токены в ответе (токенизатор Anthropic CL100k)

  • tokens_full_file_upper_bound — сколько стоило бы наивное чтение всего файла (когда это можно вычислить)

  • duration_ms, session_id и status

metrics_daily агрегирует их по (day, tool_name) со скользящим средним для длительности и итоговыми суммами для количества токенов. Upsert сводки использует инкрементальную формулу среднего, чтобы не хранить все сырые строки бесконечно:

avg_duration_ms = (old_avg * old_n + new_val) / (old_n + 1)

Используйте mast metrics --since 7d для читаемой таблицы или mast_efficiency из MCP-сессии для машиночитаемого JSON-резюме с повествованием counterfactual.


История

MAST изначально объединял BM25 с векторным поиском на основе эмбеддингов (LanceDB + локальная модель эмбеддингов ONNX). Измерения не подтвердили целесообразность его сохранения: векторное хранилище было удалено 2026-08-06 согласно решению M2 (см. ADR 003). Система до удаления — включая конвейер эмбеддингов и инструменты оценки, которые его измеряли — сохранена в git-теге mast-pre-vector-delete для тех, кто захочет воспроизвести эти доказательства.

A
license - permissive license
Not graded
quality - not tested
B
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

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables querying and analyzing code relationships by building a lightweight graph of TypeScript and Python symbols. Supports symbol lookup, reference tracking, impact analysis from diffs, and code snippet retrieval through natural language.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Fast semantic code search for AI agents — find symbols, references, and callers across any codebase.
    9
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Indexes codebases and lets AI agents retrieve precise code snippets (functions, classes, routes) instead of reading entire files, reducing token usage and improving accuracy.
    45
    7
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Token-safe code search for AI agents: queries the language-server index (clangd / Roslyn / tsserver / pyright) instead of grep and returns a token-capped file:line list — ~20x fewer tokens. Symbol-level editing + a grep→index rewrite hook. Local-only, no IDE.
    16
    11
    MIT

View all related MCP servers

Related MCP Connectors

  • Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.

  • Provide your AI coding tools with token-efficient access to up-to-date technical documentation for…

  • Enterprise code intelligence for M&A, security audits, and tech debt. Hosted server with 200k free.

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/SpikedPunchVictim/mast'

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