Skip to main content
Glama

MCP-Bifrost

Перепишите 200 методов дешёвой моделью, не пропуская ни одной строки результата через контекст дорогой — и не записывая на диск ничего, что не компилируется.

tests license python targets

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

Голова решает. Мыщцы печатают. Bifrost — это нерв между ними — и та часть, которая гарантирует, что на диск ничего не попадёт сломанным.

В примерах ниже голова — это Claude, а мышцы — DeepSeek, просто потому, что эта модель оказалась под рукой. Ни та, ни другая не обязательна. См. Рабочая модель — там объясняется, почему 7B-модель на вашей собственной машине может быть более интересным выбором.


Зачем

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

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

Оркестратор делает всё сам

Через Bifrost

202 метода × ~800 ток

~161 000 ток — превышает окно контекста

~15 000 ток

Честная версия (см. RF-4): для одной маленькой правки экономия реальна, но скромна, потому что оркестратору в любом случае обычно приходилось читать код, чтобы решить, что он хочет. Выигрыш на порядок — в объёме: это преобразования по множеству символов, где инструкцию можно написать, ничего не читая.

Именно для этого сценария это и построено. А не для «исправь эту ошибку».


Related MCP server: ropey

Когда это не стоит использовать

  • Исследовательские задачи. «Найди, почему это падает» — это не инструкция, которую Bifrost может выполнить. Она должна знать символы до того, как начнёт.

  • Одиночные мелкие правки. Арифметика токенов тут маргинальна, и мы это признаём (RF-4). Используйте штатный инструмент правки вашего агента.

  • Циклы, чувствительные к задержке. Около 2,6 с на блок, измерено на DeepSeek.

  • Всё, что не является PHP или Python. Добавление языка означает написание адаптера парсера, а не переработку ядра, — но сегодня этого нет.

  • Межфайловые рефакторинги, где форма одной правки зависит от результата другой. patch_group даёт атомарность, но не упорядочивание.

  • Кодовые базы, в которых нельзя узнать, что что-то сломалось. Каждый гейт здесь проверяет форму; ни один не понимает смысла.

Как это соотносится с Aider, Serena и fast-apply-моделями — включая то, где они лучше, — описано в docs/comparison.md.


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

you ──▶ Claude Code ──▶ MCP-Bifrost ──▶ worker model
         analyses,        parses,          writes one
         splits work      validates,       isolated block
                          applies, logs
                              │
                              ├──▶ source file (atomic splice)
                              └──▶ .bifrost/history.db

Оркестратор решает, что и как. Рабочая модель не решает ничего. Сервер — единственный компонент, которому разрешено касаться диска, и он отказывает, пока не пройдут все гейты.

Гейты проверки

Гейт

Проверяет

По умолчанию

0 — домены

блок на диске побайтно совпадает с тем, что мы отправили рабочей модели

вкл

1 — синтаксис

пересобранный файл проходит php -l / ast.parse()

вкл

2 — один символ

возвращённый блок определяю ровно один символ

вкл

3 — содержание

не исчез ни один вызов, переменная или управляющее ключевое слово

выкл

По умолчанию включены три, а не четыре. Гейт содержания — это грубая regex-проверка, которая ни разу не сработала за время калибровки, а гейт, отклоняющий хорошие патчи, хуже гейта, ждущего готовности к включению. Включите его с помощью substance_gate=True перед массовой работой.

«Проверка периметра», сравнивающая байты за пределами целевого диапазона, была спроектирована, реализовама, а затем удалена: сервер пересобирает файл как original[:start] + block + original[end:], поэтому периметр сохраняется по построению, и эта проверка никогда не может отказать. Калибровка это подтвердила — гейт сообщал 9/9, в то время как три файла остались синтаксически сломанными. См. RF-1.

Откат

Git уже является контентно-адресуемой базой данных, поэтому он используется в этом качестве. git hash-object -w перед каждым патчем даёт SHA блоба, который попадает в журнал; откат — через git cat-file blob. Дедупликация за бесплатно, работает с грязным рабочим деревом, и не нужно поддерживать никакой специфический формат снимков.


Рабочая модель

DeepSeek — это то, что было под рукой, и все измерения этой дипозитории сделаны через него. Он не обязателен и, вероятно, не самый интересного способа его запуска.

Работа рабочей модели намеренно узка. Она получает один изолированный блок и одну инструкцию и возвращает один блок. Она не выбирают файлы, не планируют изменения, не решают, что редактировать, и не видят ничего больше в кодовой базе. Это новая задача, с которой может справиться даже 7B-кодинговая модель, — и гейты существуют именно для того, чтобы ошибки слабого исполнителя были пойманы до попадания на диск, а не после.

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

  • Ваш код никогда не покидает машину. Для проприетарной кодовой базы это не предпочтение, а обязательное условие.

  • Затраты уходят в ноль именно на той нагрузке, для которой это создано, где сотни блоков за один прогон — норма, а не перебор.

  • Требование к контексту минимально. Один метод, а не файл. Окна в 8K достаточно; весь замысел в том, что рабочая модель никогда не видит больше того, что ей нужно.

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

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

Подходит любая OpenAI-совместимая точка назначения — Ollama, сервер llama.cpp, LM Studio, vLLM:

"env": {
  "BIFROST_WORKER_BASE_URL": "http://localhost:11434/v1",
  "BIFROST_WORKER_MODEL": "qwen2.5-coder:7b"
}

Ключ не нужен, когда кондиционная точка не выхода по умолчанию.

Совместимость с исполняемой моделью

Ни одна локальная модель ещё не измерена. Конечная точка настраивается, а протокол — это обычный OpenAI-совместимый чат-оtвеcompletion, но этот репозиторий не публикует утверждений, которых не замерил, — включая утверждения в свою пользу.

Инструмент существует. Укажите его на вашу конечную точку:

BIFROST_TARGET=/path/to/your/codebase \
BIFROST_WORKER_BASE_URL=http://localhost:11434/v1 \
BIFROST_WORKER_MODEL=your-model \
python3 calibratge/calibra.py --cases 9

Модель

Вале идный JSON

Идентичен байт-видивно (тество на тождество)

Без прыгающих строк

Без ограждений

Задержка

DeepSeek (deepseek-chat, API)

9/9

3/3

3/3

9/9

2,6 c

ваша модель здесь

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

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


Что покидает устройство

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

Что это не значит. Блок все-таки покидает, в открытом виде, в направлении той конечной точки, которую вы настроили. Также и инструкция — она сама может описывать внутреннюю архитектуру.

Что уже защищает. Heimdall работает до отправки, а не до записи. Там, где секрет — это самостоятельный токен, он заменяется на placeholder, рабочая модель преобразует код вокруг него, а оригинал возвращается обратно до записи файла — каждый placeholder должен возвратиться ровно один раз, иначе не записывается вообще ничего. Что нельзя безопасно исчерпать — полностью блокирует отправку. Измеренная доля ложных срабатываний на реальной кодовой базе: 2 находки на 1 291 символ, обе — корректный отказ кода, который манипулирует ключами, а не просто содержит один.

Если у вас ограничение в том, что наружу не может выйти ничего, — ответ это локальная рабочая модель, а не уменьшенный объём payload.

Спроектировано, но не готово

Два дополнения закрыли бы почти весь оставшийся разрыв. Ни одного из них пока не существует; я называю их здесь, а не прячу во issue, потому что интереснее как раз конструкция:

  • Журнал исходящего. Журнал фиксирует размер отправленного, а не сами байты. Записать его рядом с тем, что вернулось, почти ничего не стоит, и это превращает «верь нам» в «бери и проверь».

  • Редактирование комментариев и литералов. Heimdall (демаскирует) только то, что похоже на секреты. Parser уже строить абстрактное синтаксическое дерево, поэтому комментарии и строки-литералы — которые часто являются наиболее ценными рисками и часто не связаны с трансформацией — можно было бы заменить на непрозрачные маркеры и восстанавливать их при возврате.

Очевидное возражение против второго: качество может пострадать, если рабочая модель не видит имён. Это измеримый вопрос, а не аргумент: девять случаев с редактированием, девять без неё, calibratge/calibra.py. Какой бы ни был результат — он будет опубликован.


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

Python 3.11+. Нет зависимостей в момент применения — сервер работает на стандартной библиотеке, каждый язык разбирается с помощью собственного автоматизированного инструментария (php — внешним бинарником, ast — из stdlib).

pipx install mcp-bifrost      # or: uv tool install mcp-bifrost

Добавьте его в .mcp.json в проект, который вы сопира патчить:

{
  "mcpServers": {
    "bifrost": {
      "command": "mcp-bifrost",
      "env": { "BIFROST_DB": ".bifrost/history.db" }
    }
  }
}

Или из исходного кода, без установки:

git clone https://github.com/FixemBCN/MCP-Bifrost.git
cd MCP-Bifrost
python3 -m unittest discover tests    # 128 tests, ~15s
python3 -m mcp_bifrost.server         # same server, PYTHONPATH=.

Ключ в это файл не идёт. Положите его в .bifrost.env в корню вашего проекта — сервер читает его, когда переменной окружения нет:

echo "DEEPSEEK_API_KEY=sk-..." > .bifrost.env
chmod 600 .bifrost.env
echo ".bifrost.env" >> .gitignore

Или вообще откажитесь от ключа и направьте BIFROST_WORKER_BASE_URL на локальную модель. Полные подготовки и то, что нужно сделать before направлять это на что-то важное, описано в руководстве.

Ниструменты

Инструмент

Что делает

fix_symbols

одна инструкция для множества виртуальных символов — главный инструмент

fix_symbol / fix_range

переписать один символ или явно заданный диапазон строк

insert_symbol / insert_range

добавить метод или ветвь в switch-роутер

create_file

создать новый файл, опционально по аналогии с существующим

patch_group

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

export_docs / publish_session

сформировать changelog из журнала; пакетно — в ветку для ревью

revert_patch / revert_session

отменить один патч или весь пакет


Калибровка

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

Дан реальный метод из реальной кодовой базы, упакованный в компактную схему — вернёт ли воркер код, который можно применить, ничего не сломав?

Ответ даёт стенд в calibratge/. Никаких зависимостей — стандартная библиотека Python плюс бинарник php.

export BIFROST_TARGET=/path/to/your/codebase
python3 calibratge/calibra.py --dry-run    # show cases, no API calls
export DEEPSEEK_API_KEY=...
python3 calibratge/calibra.py --cases 9

Результат: исходное предположение подтверждается. 9/9 валидных JSON, 3/3 побайтово совпали на задаче тождественности, 3/3 без потери исходных строк, 0/9 обёрнуто в markdown-ограничители, средняя задержка 2,6 с.

Он также поймал баг со смещением байтов, который к воркеру не имел никакого отношения и в продакшене молча повреждал бы файлы. Полный отчёт: docs/calibration.md.


Структура репозитория

Путь

Что находится

mcp_bifrost/

сервер

docs/

руководство, архитектура, критический разбор, калибровка, сравнение, лицензирование

tests/

128 тестов

brainstorm/

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

calibratge/

измерительный стенд


За кулисами

Если говорить начистоту: ни одна строка в этой кодовой базе не была написана вручную. Она была задумана, подвергнута сомнению, реализована, протестирована и документирована в процессе с участием ИИ, которым руководил человек. Вот что это означало на деле, настолько точно, насколько можно выразить.

Человек — задача, решения, направление. Я дал исходную спецификацию и принимал все продуктовые решения: какая воркер-модель, какие языки, что вырезать, что делать следующим, лицензию, название и когда остановиться. Несколько решений я пересмотрел — например, лицензия начиналась как source-available с запретом перепродажи, а закончилась Apache-2.0, когда я понял, что распространение важнее контроля. Я также определял, что система обязана отказываться делать, — и это оказалось более значимой половиной решений.

Claude Opus — состязательное проектирование. До реализации Claude посмотрел на спецификацию со стороны и выявил двенадцать замечаний. Два из них похороняли элементы дизайна, которые я утвердил: центральная «проверка периметра», на которую опиралась спецификация, оказалась неспособной провалиться; и заявленное обоснование проекта — экономия токенов — показало себя ничтожной для одиночных правок и решающей только на массовом объёме. Оба замечания сохранены без изменений в brainstorm/.

Измерения до кода. Вместо того чтобы довериться дизайну, сначала построили калибровочный стенд и запустили его на реальном воркере с настоящим кодом. Он не прошёл 6 кейсов из 9 — и ни в одном не был виноват воркер. Причина — баг со смещением байтов, который молча портил бы любой файл с буквой с диакритикой. Он также опроверг два из выводов самого Claude. Эти поправки стоят поверх исходных утверждений, а не заменяют их.

Claude Opus — ядро; другие модели — периферия. Клод написал разбор, применение патчей, шлюзы валидации, работу с секретами и движок напрямую. Два периферийных модуля и весь набор тестов были переданы моделям поменьше (Haiku и Sonnet), которые работали как субагенты. Разделение было сознательным, а не экономическим: модель, с нуля начинающая писать код патчей, с большой долей вероятности вернула бы баг со смещению байтов, потому что способ, который напрашивается сам первым, — неправильный.

Делегированные модели нашли четыре реальные ошибки в коде, написанном Claude, в том числе ту, что отвязала docblock документуемого метода, и ту, где вложенные switch-инструкции молча теряли ветви. Обе проходили все шлюзы валидации. Только состязательная проверка моделью, которой больше ничего на этом коде не светит, сумела их поймать.

Человек — проверка и приёмка. Я управлял последовательностью, смотрел результаты, оспаривал заявки и решал, что остаётся. Claude выполнял прогоны валидации и калибровки; я читал то, что возвращалось, и решал, что это значит.

Чего этот процесс не дал

Ни один человек не прочитал all ~7 400 строк этого репозитория — примерно 4 100 строк сервера, 2 700 тестов и 600 строк измерительного стенда — построчно. Целевая имاعد здесь — из тестов, проверенных против умышленно сломанного кода, из измерений на настоящей кодовой базе и из дизайна, который пишет только то, что сам может проверить, — никакой ручной аудит.

Если для инструмента, который редактирует ваши исходные файлы, вы хотите другой уверенности — это разумно, и в разделе «Ответственность» подробно рассказано, что шлюзы ловят, а что пропукают.

Почему это в README

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

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


Документация

Документ

Назначение

Руководство

что это, что может, как установить и за что вы ответственны

Архитектура

что строится и почему

Критический разбор

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

Результаты калибровки

что воркер на самом деле делал, когда его просили

Сравнение

как это рядом с Aider, Serena и fast-apply и в чём выигрывают они

Лицензирование

что мы потребляем, что мы предоставляем

В brainstorm/ лежит рабочий журнал: исходная спецификация, дневник разработки через пять ревизий, состязательный обзор и резубcalт каты калибровки. docs/ — справочник, и при расхождении главенствует он.


Ответственность

Этот инструмент автоматически редактирует ваши исходные файлы с помощью языковой модельни. Лицензия Apache 2.0 означает, что он предоставляется как есть, без каких-либо гарантий: вы отвечаете за то, что он сделает с вашим кодом. Читайте диффы, запускайте тесты и выкатывайте осознанно. В руководстве точно сказано, какие шлюзы помогают, а какие нет.

Вклад

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

Единственная конвенция, и она ключевая: каждый тест должен быть способен провалиться. Подробности — в руководстве.

Лицензия

Apache License 2.0.

Построено на Model Context Protocol, распространяющегося под лицензией MIT, Anthropic, PBC. MCP-Bifrost — независимый проект, не афиллирован с Anthropic, PBC, их одобрён и не спонсируется им.

Available Tools

11 tools
create_fileB

Write a new source file. Never overwrites. Pass model_from to generate BY ANALOGY: the worker is handed an existing sibling as a structural exemplar and traces its shape, naming and error handling rather than inventing its own. Where a codebase already has many files of one kind, this is by far the most reliable way to add another — the worker does not need to know your conventions, it needs to copy them.

Inputs: file_path (required), instruction (required), verify, model_from, +1 more.

export_docsA

Turn the patch log into readable documentation — a changelog, release notes, a summary of a batch. Every patch already recorded why it was made, at no cost to your context; this reads that back. Runs ONLY when asked: nothing generates it automatically.

Inputs: group, since, title, output_path, +1 more.

fix_rangeA

Rewrite an explicit line range. The escape hatch for code that does not live inside a symbol — module-level configuration, a branch of a switch, markup embedded in the source. Prefer fix_symbol where one applies: line numbers move when earlier patches land, and a stale range is rejected rather than applied.

Inputs: end_line (required), file_path (required), start_line (required), instruction (required), +2 more.

fix_symbolA

Rewrite one named function, method or class in place. The symbol is extracted with the language's own parser, sent to a worker model, validated, and spliced back atomically. Addressing by name is immune to line drift, so it is safe to issue many against the same file. Skip this only when the edit is too small for a symbol boundary to matter — a one-line typo, a single config value, a comment. Anything that changes what a function does should go through here even when you already read the code: unlike a manual edit, this re-resolves the symbol by name (immune to line drift from earlier edits landing in the same file), validates syntax before writing, and is rollback-able from a saved git blob. Having read the file first buys a manual edit none of that.

Inputs: file_path (required), instruction (required), symbol_name (required), verify, +2 more.

fix_symbolsA

Apply ONE instruction across MANY symbols. This is the tool this server exists for. For a single target, use fix_symbol instead — the parallel worker calls here only pay off once there is more than one. The order-of-magnitude win is a transformation stated once and applied to symbols you never read: 'add a docblock to every method here', 'switch every call to the new API'. Worker calls run in parallel, writes run in series, and each symbol is re-resolved by name just before its write, so earlier patches moving later offsets is not a problem.

Inputs: targets (required), instruction, max_parallel.

insert_caseA

Add a branch to a switch. A case label is not a symbol, so no parser addresses it — but in a router-style file it is the extension point every new endpoint goes through. Anchored to a neighbouring case label, which stays stable across a batch the way line numbers do not. A label that already exists is rejected: PHP takes the first match and silently ignores the rest, so a duplicate is dead code that looks alive.

Inputs: file_path (required), after_case (required), instruction (required), context, +1 more.

insert_symbolB

Add a new function, method or class next to an existing one. Classes are addressable, so a class is a valid anchor and a valid thing to insert. Anchoring to a symbol rather than a line number is what makes this usable in a batch: the anchor does not move when everything above it changes. The anchor is also shown to the worker as a style reference, so the new code matches its neighbours.

Inputs: anchor (required), position (required), file_path (required), instruction (required), +2 more.

patch_groupA

Apply several operations as one transaction: all of them land, or none do. Use whenever a change spans more than one file — a new class plus the require_once that references it plus the method that returns it. Applying that halfway leaves the project worse than not starting. On failure everything already applied is rolled back in reverse order.

Inputs: operations (required).

publish_sessionA

Put this session's changes on a branch as one reviewable commit, with a body listing every change and the reason recorded for it. Worth doing after any sizeable batch: a batch loose in the working tree is close to unreviewable, and where there is no test suite, review is the only safety net there is. Opening a pull request is opt-in and pushes to the remote — ask before setting it.

Inputs: branch (required), subject (required), base, draft, +1 more.

revert_patchB

Undo one patch by id, restoring the file from the blob saved in git's object store before it was applied.

Inputs: patch_id (required).

revert_sessionA

Undo every patch applied in this session, newest first. Use when a batch has gone wrong partway: you rarely want to undo one patch out of twenty, you want to undo the batch.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 11 tools

    Disambiguation5/5

    Tools are sharply delineated by scope: fix_symbols for batch symbol edits, fix_symbol for single symbols, fix_range for line ranges, insert_symbol/insert_case for insertions, create_file for new files. The descriptions explicitly guide when to use each, preventing misselection between overlapping editing operations.

    Naming Consistency5/5

    All 11 tool names use lowercase snake_case with a consistent verb_noun or verb_object pattern (fix_symbols, insert_symbol, create_file, patch_group, revert_patch). No deviations or mixed conventions.

    Tool Count5/5

    11 tools is well-scoped for a code transformation server. Each tool fills a distinct niche: single/multi/range edits, insertions, file creation, transactions, documentation, publishing, and reverts.

    Completeness4/5

    Core lifecycle is covered: create, modify, insert, batch transaction, revert, and publish. Minor gaps exist, such as no explicit delete/remove operation and no read/get tool, but agents can work around these using fix_range or fix_symbol.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers