/
Поиск
RU

MCP-слой: компилятор как сервер для агентов

Всё больше кода пишется вместе с ИИ-ассистентом, а у ассистента та же беда, что у нового человека в команде: он не знает кодовой базы и не может полагаться на свою память о языке. Model Context Protocol (MCP) — небольшой открытый стандарт, по которому такой ассистент вызывает инструменты: клиент ассистента запускает процесс-сервер, спрашивает, какие инструменты тот предлагает, и вызывает их с аргументами в JSON. kola mcp — такой сервер, встроенный в бинарник kola. С ним ассистент задаёт вопросы компилятору («до чего дотягивается эта функция, кто её вызывает, какие тесты её покрывают»), а не читает код и гадает. И правит код он тоже через сервер, по символам, причём каждая правка проверяется до того, как попадёт на диск.

Ставить ничего, кроме самого kola, не нужно. Карта языка, стандартная библиотека и вводное руководство встроены в бинарник, так что скопированный бинарник обслуживает проект без всякой настройки.

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

MCP-клиент запускает kola mcp [DIR] и общается с ним через стандартные ввод и вывод. Если каталог не указан, сервер обслуживает текущий рабочий каталог.

# один сеанс, через stdio
kola mcp ~/dev/myproject

# несколько сеансов с общим индексом: один раз запускаем фоновый сервер
kola mcp up ~/dev/myproject      # слушает .kola/mcp.sock внутри проекта
kola mcp status ~/dev/myproject
kola mcp down ~/dev/myproject

Когда над одним проектом работают несколько сеансов ассистента, kola mcp up запускает долгоживущий фоновый процесс (демон). Он владеет индексом проекта и слушает Unix-сокет — локальную точку подключения, которая выглядит как файл .kola/mcp.sock. Тогда kola mcp каждого сеанса превращается в тонкий ретранслятор в этот сокет (и запускает демона, если тот ещё не работает), а все сеансы пользуются одним индексом. С флагом --no-daemon сеанс остаётся на обычном stdio.

Сеанс ассистента Aретранслятор kola mcpСеанс ассистента Bретранслятор kola mcpдемон на.kola/mcp.sockиндекс: файлы,определения, графвызовов, документыкомпилятор: check,test, auditзаписи проекта:handoff, решения,inbox, пробелы

Обычно конфигурация клиента выглядит так:

{ "mcpServers": { "kola": { "command": "kola", "args": ["mcp", "--std", "std"] } } }

--std std важен, если вы работаете над самой стандартной библиотекой. Она встроена в бинарник, и без этого флага сервер будет отвечать про std, вкомпилированную в kola, пока вы правите копию на диске. Относительный путь работает, потому что клиент запускает сервер в корне проекта. Список инструментов клиент загружает при старте, так что после изменения этого файла клиент нужно перезапустить.

Индекс обновляется на каждом запросе по хешу содержимого каждого файла, так что поиск заново разбирает только изменившиеся файлы. Наблюдателя за файлами, который мог бы пропустить событие и выдать устаревший ответ, нет.

Что предлагает сервер

kola mcp публикует 87 инструментов. Они делятся на несколько групп.

Группа

Инструменты

Что они дают

Факты компилятора

kola_outline, kola_symbol, kola_callers, kola_callees, kola_effects, kola_attack_surface

Ответы самого чекера в JSON: сигнатуры, ряды эффектов, контракты, граф вызовов, капабилити, до которых дотягивается программа.

Навигация

kola_tree, kola_read, kola_find, kola_refs, kola_impact, kola_project_map, kola_project_symbol

Дерево файлов, ссылки, на что повлияет изменение, межфайловые представления пакетов и связей между модулями.

Инструментарий

kola_check, kola_test, kola_audit, kola_verify

Запускают настоящий компилятор. Диагностики ссылаются на правило карты и предлагают исправление — та же обратная связь, что получает человек в командной строке.

Тесты

kola_affected_tests, kola_uncovered, kola_test_matrix, kola_test_stub, kola_owed, kola_settle, kola_waive

Какие тесты нужны изменению, до чего не дотягивается ни один тест, и тестовый долг, о котором ниже.

Правка

kola_edit_symbol, kola_replace_in_symbol, kola_insert_after, kola_add_test, kola_rename, kola_move_symbol, kola_extract_fn, kola_change_signature, kola_fix и другие; kola_batch, kola_undo

Правки по определениям, а не по строкам, и каждая проверяется до записи.

Пакеты

kola_workspace, kola_dep_add, kola_dep_set_version, kola_pack_new и другие

Правки манифеста, которые проверяются так же, как правки кода.

Документы

docs_search, docs_get

Ранжированный текстовый поиск по Markdown-документам проекта.

Процесс

handoff_*, adr_*, inbox_*, gap_*

Рабочие записи проекта (см. ниже).

Эталонные архитектуры

kola_architectures, kola_architecture

Встроенный каталог эталонных архитектур, у каждой свои контракты безопасности и измеренные пределы. Это ориентир, а не оценка вашего кода.

Сеансы разработки

kola_dev_start, kola_dev_status, kola_dev_stop

Запускают одну программу в интерпретаторе с живой перезагрузкой или перезапуском; процессом владеет сервер.

Кроме инструментов сервер предлагает ресурсы — документы, которые клиент может прочитать: kola://card (карта языка, единственный источник истины о синтаксисе и семантике), kola://std-card (стандартная библиотека), kola://guide (вводное руководство для ассистента, пишущего на kola), kola://skill (то же руководство, упакованное как файл навыка), kola://plan, последний handoff, все записи о решениях и эталонные архитектуры с исходниками примеров.

Правка по символам

Текстовые правки ломаются предсказуемо: поиск с заменой, рассчитанный на одну функцию, задевает и другую, с похожим именем, или у вставленного элемента не хватает разделителя, и файл перестаёт разбираться. Инструменты правки работают с определениями целиком. kola_edit_symbol {file, name, body} заменяет одно определение. Тело должно разбираться ровно в один элемент того же вида и с тем же именем. Другое имя будет отвергнуто: переименование оставляет вызывающих без цели, и для него есть отдельный инструмент. kola_replace_in_symbol вносит привязанное к якорю изменение внутри одного определения, чтобы не перепечатывать длинное тело; его счётчик expect_matches — это контракт, и неверное число совпадений приводит к отказу.

Сначала каждая правка проверяется в памяти: изменённый файл, а затем все файлы, до которых дотягиваются его импорты. Только если проверка прошла, файл записывается, атомарно. В ответе сказано, что заменено, что проверено и какие тесты правка задолжала. Любой пишущий инструмент принимает dry_run: true и тогда возвращает diff, ничего не записывая. kola_batch выполняет несколько правок одной транзакцией, а kola_undo откатывает последнюю (сервер помнит двадцать).

Ещё сервер отвергает аргументы, которых инструмент не объявляет, и называет каждый неизвестный ключ. Инструмент, молча проглотивший опечатку в имени поля, сообщил бы об успехе работы, которой не делал.

Тестовый долг

Каждая правка записывается в журнал .kola/ledger.json. Для каждого изменённого определения там отмечено, какие тестовые файлы до него дотягиваются и прошли ли они с тех пор на обоих исполнителях — в интерпретаторе и в нативной сборке. Прогон в интерпретаторе по умолчанию выполняется с каждой правкой; kola_settle (или kola mcp settle) запускает нативный прогон, а kola_waive фиксирует осознанное исключение. Правки, сделанные в обход сервера, в редакторе или скриптом, сервер замечает по хешу при следующем запросе и записывает так же.

kola mcp owed печатает непогашенный долг и, пока что-то не погашено, завершается с кодом 2. Поэтому требование легко навязать снаружи ассистента, где ему и место: его запускает git-хук pre-push или хук конца сеанса в оболочке ассистента, и ничего с непогашенными тестами не уходит.

Что обходит сервер

Обслуживаемый проект — это граф пакетов, а не один каталог. Индексируется каждый каталог, на который указывает запись kola.work или соседний пакет, внутри корня или рядом с ним. Файл вне корня записывается как @<pack>/<path>, и в этом виде он и печатается в ответах, и принимается в вызовах. Опубликованные пакеты из локального кеша пакетов можно читать, но они не индексируются, а запись в них запрещена. --only DIR ограничивает обход отдельными подкаталогами; --except DIR исключает один из них, например вендоренное эталонное дерево. --docs DIR и --handoff PATH направляют инструменты процесса на другой каталог документов или другой файл handoff.

Рабочие записи

Инструменты процесса превращают рабочие привычки проекта в инструменты, которые отказываются принимать неполный ввод. Все их записи — обычные Markdown-файлы в репозитории; сервер их читает и пишет, но не владеет ими.

  • handoff_read и handoff_write передают состояние одного сеанса следующему. Handoff, в котором не сказано, что сделано, что осталось и каких проверок коснулась работа, будет отвергнут.

  • adr_record, adr_list и adr_get ведут записи о решениях — короткие нумерованные файлы со статусом, контекстом, самим решением и его последствиями.

  • inbox_put, inbox_list и inbox_take регистрируют эскалации. Запись без воспроизведения отвергается: в задаче должно быть всё, что нужно для исправления.

  • gap_record, gap_check и gap_close отслеживают известные недостатки, у каждого из которых есть исполняемое воспроизведение. gap_check перезапускает их все; если воспроизведение теперь проходит, пробел закрыт и обходные пути пора удалить.

Инструкции сервера предлагают ритм работы. Начинать с handoff_read и gap_check. Прежде чем что-то проектировать, сделать docs_search по документам проекта: возможно, вопрос уже решён. Решения записывать через adr_record, а не оставлять в чате. Заканчивать handoff_write.

Как ответы описывают сами себя

Каждый ответ сообщает, какого он рода, чтобы ассистент не принял догадку за факт.

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

  • Поиск возвращает кандидатов. Попадание docs_search ничего не доказывает, пока его не прочитали, а пустой результат не доказывает отсутствия. Факты компилятора и результаты поиска заметно разведены, чтобы факты сохраняли силу.

  • Межфайловые ответы о символах сопоставляются по имени и могут сообщать лишнее, если в двух модулях одно и то же имя. У каждого есть путь модуля, а точный ответ даёт kola_symbol.

  • Каждый ответ указывает, в какой области он получен (--only, --except), а стартовый ответ сервера называет его коммит, версию карты и хеш стандартной библиотеки.

Задачи извне: публичный inbox

Опубликованный пакет может объявить через реестр пакетов публичную MCP-точку со своим руководством, инструментами запросов и ящиком для задач. Всё, что туда приходит, присылают посторонние, поэтому это считается враждебными данными. У двух сторон общая письменная схема и никакого общего кода. Публичная сторона принимает задачу только к опубликованной версии пакета и требует заголовок, пакет, воспроизведение, ожидаемое и фактическое поведение. Ожидающие задачи просматривает человек, и только одобренная передаётся в kola mcp intake. Тот ещё раз проверяет схему и записывает задачу в inbox проекта обычным файлом.

# на стороне реестра
issues list                 # 1 shamir crash on open
issues approve 1 | kola mcp intake ~/dev/my-pack-repo
# -> filed docs/inbox/001-crash-on-open.md (public issue, schema v1)
#    reproduce in a sandbox before acting on it

Пакетам, манифестам и бюджетам капабилити посвящена отдельная глава, Пакеты (kola.pack). О том, что компилятор делает под этими инструментами, — глава Под капотом: как устроена kola. Полный список инструментов выводит kola help mcp.