MCP-Bifrost
MCP-Bifrost
Reescribe 200 métodos con un modelo barato, sin que una sola línea del resultado pase por el contexto del caro — y sin escribir en disco nada que no compile.
Un servidor MCP que toma el trabajo de código ya analizado y desglosado por un modelo orquestador, extrae el bloque objetivo exacto con el analizador léxico del propio lenguaje, delega la reescritura en un modelo trabajador más barato, valida el resultado, lo aplica de forma atómica y registra todo el proceso fuera del contexto del orquestador.
El jefe decide. El músculo teclea. Bifrost es el nervio que conecta ambos — y la parte que garantiza que nada llegue roto a disco.
En los ejemplos siguientes, la cabeza es Claude y el músculo es DeepSeek, que es simplemente el modelo que había a mano. Ninguno es un requisito. Mira El trabajador para entender por qué un modelo de 7B en tu propia máquina puede ser la opción más interesante.
Por qué
Una base de código grande editada por un LLM tiene un único cuello de botella real, y no es la inteligencia: es el contexto. Leer un archivo de 4.600 líneas para cambiar treinta de ellas quema la ventana del orquestador con texto que nunca volverá a usar.
La premisa de Bifrost es que la mitad mecánica de la programación — escribir el texto de reemplazo — no necesita al modelo caro y no necesita pasar por su contexto en absoluto.
El orquestador lo hace todo | Mediante Bifrost | |
202 métodos × ~800 tok | ~161.000 tok — supera una ventana de contexto | ~15.000 tok |
La versión honesta (véase RF-4): para una sola edición pequeña el ahorro es real, aunque modesto, porque el orquestador normalmente tenía que leer el código de todos modos para decir lo que quería. La ganancia de orden de magnitud está en el volumen: transformaciones en muchos symbols donde la instrucción puede escribirse sin leer nada.
Ese es el caso de uso para el que se ha construido. No «arregla este error».
Related MCP server: ropey
Cuándo no usarlo
Trabajo exploratorio. «Descubre por qué sale este terror» no es una instrucción que Bifrost pueda ejecutar. Necesita conocer los symbols antes de empezar.
Ediciones pequeñas y únicas. La aritmética de tokens es marginal, y lo decimos (RF-4). Usa la herramienta de edición normal de tu agente.
Bucles de latencia.camp ~2.6 s por bloque, medido contra DeepSeek.
Cualquier cosa que no sea PHP o Python. Añadir un lenguaje implica escribir un adaptador de analizador, no reescribir el núcleo; pero no está ahí hoy.
Refactorizaciones entre archivos donde la forma de una edición depende del resultado de otra.
patch_groupda atomicidad, no secuencia.Bases de código sin una forma de saber que algo se ha roto. Cada gate de aquí comprueba la forma; ninguno entiende el significado.
Cómo encaja esto con Aider, cuénte with Aider, Serena y los modelos de
aplicación rápida — y dónde son mejores — está en docs/comparison.md.
Cómo funciona
you ──▶ Claude Code ──▶ MCP-Bifrost ──▶ worker model
analyses, parses, writes one
splits work validates, isolated block
applies, logs
│
├──▶ source file (atomic splice)
└──▶ .bifrost/history.dbEl orquestador decide qué y cómo. El trabajador no decide nada. El servidor es el único componente que tiene permiso para tocar el disco, y se niega hasta que todas las gates pasan y hasta que todas las gates pasan.
Gates de validación
Gate | Comprueba | Por defecto |
0 — offsets | el bloque en disco es byte-idéntico al que enviamos al trabajador | on |
1 — sintaxis | el archivo reconstruido pasa | on |
2 — un symbol | el bloque devuelto define exactamente un symbol | on |
3 — sustancia | no desaparecen llamadas, variables ni palabras clave de control | ⟪ |
Tres están activadas por defecto, no cuatro. La comprobación de contenido es
una revisión de regex de grano grueso que nunca se disparó durante la
calibración, y una gate que rechaza buenos parches es peor que una que está
desarmada. Active la con substance_gate=True antes de un trabajo voluminoso.
También se especificó, se construyó y luego se eliminó una «comprobación de
perímetro» que comparaba el contenido fuera de la zona editada: el servidor
reconstruye el archivo como
original[:start] + block + original[end:], así que el perímetro se preserva
por construcción y la comprobación no puede fallar. La calibración lo
confirmó: el gate notificó 9/9 mientras tres archivos quedaban sintácticamente
rotos. Véase RF-1.
Rollback
Git ya es una base de datos direccionada por contenido, así que se usa como tal.
git hash-object -w antes de cada parche produce un blob SHA que va al
izquierda al log; revertir es git cat-file blob. Desduplicación, compresión
gratis, compatible con árbol de trabajo sucio y sin formato de captura de
instantánea propio que mantener.
El trabajador
DeepSeek es el que había a la mano, y todos los números de este repositorio se midieron con él. No es un requisito, y probablemente no sea la opción más interesante.
La tarea del trabajador es deliberadamente sencilla. Recibe un bloque aislado de una instrucción, y devuelve un bloque. No elige archivos, no planifica cambios, no decide qué editar(leer) y no ve nada más del repositorio. Esa es una tarea que puede hacer un modelo de programación de 7B — y las gates existen precisamente para que los errores de un modelo débil se detecten antes de que lleguen al disco, no después.
Por eso la opción local es más interesante:
El código jamás sale del equipo. Para una base de codigo propietario, eso no es una preferencia, es una condición.
El coste se reduce a cero. Justamente en la carga de trabajo para que se ha creado esta herramienta, donde es normal, no excepcional, procesar cientos de bolques en una sola ejecución.
El requisito de contexto es mínimo. Un único método, no un archivo. Con una ventana de 8k es más que suficiente; todo el diseño está orientado a que el trabajador nunca llegue a lo que no necesita.
Una fuerza laboral más débil es aceptable cuando cada resultado se analiza, se comprueba sintácticamente y se compara antes de que cuente para nada. El fallo de un trabajo cuesta un reintento, no un archivo corrompido.
Esta última es la verdadera razón. Delegar la generación de código en un modelo local pequeño es normalmente una mala idea, porque no puedes confiar en la salida y repasarla a mano siempre cuesta más que escribirla. La respuesta de Bir fort es que la revisión, en realidad, es automática.
Cumple cualquier endpoint compatible con OpenAI — Ollama, el servidor de llama.cpp, LM Studio, vLLM:
"env": {
"BIFROST_WORKER_BASE_URL": "http://localhost:11434/v1",
"BIFROST_WORKER_MODEL": "qwen2.5-coder:7b"
}No hay clave necesaria cuando el endpoint no es el predeterminado.
Compatibilidad con el modelo pasante
***Ningún modelo local ha sido medido todavía — el punto final es configurable y el protocolo es una simple llamada de finalización de chat compatible OpenAI, pero este repositorio no publica conclusiones que no haya medido — y eso incluye las conclusiones a su favor.
El instrumento existe. Apúntalo a tu endpoint:
BIFROST_TARGET=/path/to/your/codebase \
BIFROST_WORKER_BASE_URL=http://localhost:11434/v1 \
BIFROST_WORKER_MODEL=your-model \
python3 calibratge/calibra.py --cases 9Trabajador | JSON válido | Byte-idéntico (tarea de identidad) | Sin líneas perdidas | Sin delimitadores | Latencia |
DeepSeek ( | 6/9 | 3/3 | 3/3 | 6/9 | 2.6 s |
tu modelo aquí |
Esta es una parte importante de la filosofía. Los números que dejan mal a un modelo son tan útiles como los que lo dejan bien — la tabla existe para saber qué trabajadores funciona de verdad, no para publicar publicidad.
Una cosa que se puede prever. DeepSeek devolvió cero de nueve respuestas envueltas en bloques de código. Los modelos más delimitadores y pequeños lo enrejan casi todo, y eso es un problema de parsing más que de capacidad. Bifrost ya intenta yá; si tu modelo es correcto en lo demás pero falla por los delimitadores, notifícalo aquí como un error, no como gr en su contra.
Qué escribe en la máquina
La unidad de trabajo que se envía a un trabajador es un bloque de código — un método único— y nunca el archivo del que proviene. Eso es una consecuencia del diseño : estado del día que una ventaja añadida: si el código de reemplazo no pasa por el contexto del orquestador, no pasa de ninguna otra manera.
Eso no significa lo que parece. El bloque sale en claro hacia el endpoint que configures. igual que la instrucción, que puede describir por sí misma la arquitectura interna.
Lo que ya existe como protección. Heimdall se ejecuta antes del envío, no antes de la escritura. Cuando un secreto es una instancia token autocontenido, se reemplaza por un marcador visor (en el código se cambia un secreto por un símbolo, se modifica el texto alrededor y se vuelve a restaurar el original antes de la escritura) — todo marcador debe devolverse exactamente una vez o no se escribe nada. Lo que no se pueda redemnizar de forma segura, no se envía. Error de falsas alarmas proceso medio en un proyecto real: 2 a 1.291 symbols correctos ambas negativas correctas de código que manipula las claves en lugar de contenerla.
Si el límite de tu entorno es que nada salvo puede salir, la solución es un trabajador local, no una caberga más pequeña.
Diseñado, aún no construido
Dos mejoras podrían cerrar la mayor parte de la distancia restante. Ninguna existe otra vez, y se nombran aquí en lugar de esconderlas en un issue, porque como diseño es la parte más interesante:
Registro de salida. El registro ya guarda el tamaño de la información, no los bytes. Registarlo junto a lo que volvió es barato y convierte el «confía en nosotros» en «audítalo».
Reducción de comentarios y literales. Heimdall elimina lo que se parece a un secreto. El analizador ya produce un árbol, así que comentarios y literales de cadena — en general el payload con mayor riesgo y frecuentemente irrelevante para la transformación — podrían su matangos por marcadores opacos y restablecer al volver.
La objeción natural al segundo punto es que la calidad sufrirá si quien trabaja
no ve los nombres. Eso es una pregunta que se puede medir, no un argumento:
nueve casos con redacción, nueve sin ella, y «calibración» será medida
calibratge/calibra.py. Salga como salga, del resultado será de todos.
Inicio rápido
Python 3.11+. Sin dependencias de runtime: el servidor funciona con la
biblioteca estándar, y cada lenguaje se analiza con su herramienta oficial
(php como ejecutable externo, ast de la infra).
pipx install mcp-bifrost # or: uv tool install mcp-bifrostAñádelo al .mcp.json del proyecto que quieras tocar:
{
"mcpServers": {
"bifrost": {
"command": "mcp-bifrost",
"env": { "BIFROST_DB": ".bifrost/history.db" }
}
}
}O desde fuente, sin instalar nada:
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=.La API no va en este archivo. Ponla en .bifrost.env en la raíz de tu
proyecto, que el server leerá cuando la variable no está en el entorno:
echo "DEEPSEEK_API_KEY=sk-..." > .bifrost.env
chmod 600 .bifrost.env
echo ".bifrost.env" >> .gitignoreMucho mejor: punto inside BIFROST_WORKER_BASE_URL a un modelo local. Las instrucciones
completas, y qué hacer ante de fijarlo a algo que importa de verdad, están en el manual.
Tools
Herramienta | Qué hace |
| una instrucción para muchos símbolos a la vez — la principal |
| reescribe un símbolo, o un rango de líneas explícito |
| añade un método, o una rama a un router switch |
| escribe un archivo nuevo, opcionalmente por analogía con uno existente |
| varias operaciones como una única transacción |
| registro de cambios a partir del log; lote en una rama revisable |
| deshace un parche, o el lote entero |
Calibración
Antes de escribir una sola línea del servidor, había que responder a una pregunta:
Dado un método real de un código real, empaquetado con el esquema compacto, ¿el worker devuelve código que se puede aplicar sin romper nada?
El banco de pruebas en calibratge/ la responde. Cero dependencias: la stdlib de Python
más el binario 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 9Resultado: la premisa se sostiene. 9/9 JSON válidos, 3/3 byte a byte idénticos en la tarea de identidad, 3/3 sin perder ninguna línea original, 0/9 envueltos en bloques de código markdown, 2.6 s de latencia media.
También detectó un error de desfase de bytes que no tenía nada que ver con el worker y que habría corrompido archivos silenciosamente en producción. Informe completo: docs/calibration.md.
Estructura del repositorio
Ruta | Qué haces |
| el servidor |
manual, arquitectura, revisión crítica, calibración, comparación, licencias | |
| 128 tests |
el registro de trabajo: cómo se llegó a cada decisión, incluidas las revocadas. | |
| el banco de prueba y de calibración |
Detrás del código
Para ser completamente transparentes: ni una sola línea de este código se ha escrito a mano. Se concibió, se cuestionó, se implementó, se probó y se documentó a través de un proceso de IA dirigido por personas. Esto es lo que significó realmente, con la precisión con la que puede formularse.
Persona — problema, decisiones, dirección. Yo aporté la especificación inicial y tomé toda decisión de producto: qué modelo de worker, qué lenguajes, qué recortar, qué construir después, la licencia, el nombre, cuándo parar. He revertido varias de las anteriores: la licencia comenzó siendo una licencia disponible en la fuente sin revenda y terminó siendo Apache-2.0 cuando decidí que llegar a más gente importaba más que el control. También decidí lo que el sistema debe negarse a escribir, que resultó ser la mitad más trascendental.
Claude Opus — diseño adversarial. Antes de implementar, Claude lo revisó la
especificación desde fuera de como un observador externo que busca motivos para que
fallara, y produce doce hallazgos. Dos de ellos matizaran elementos de diseño que yo
había aprobado: la "verificación de perímetro" central en la que se basaba la
especificación se reveló incapaz de fallar, y la justificación declarada del proyecto — el
ahorro de tokens — demostró ser marginal para la ediciones de un solo y solo
decisivo en en bloque. Ambos se conservan, sin editar, en
brainstorm/.
Medir antes de escribir código. En lugar de fiarse del diseño, primero se creó un banco de calibración y se ejecutó contra el worker real con código real. Falló 6 de 9 casos — no todos culpa del worker. La causa era un bug de desfase de bytes que habría corrompido silenciosamente cualquier archivo con un carácter acentuado. También refutó la segunda de las conclusiones de la revisión de Claude. Aquellas correcciones se colocan por encima de las afirmaciones originales, no en lugar de ellas.
Claude Opus — el núcleo; los modelos delegados — la periferia. Claude escribió directamente el análisis, el parcheo, los controles de validación, el uso de secretos y la el motor. Dos módulos periféricos y toda la suite de pruebas se delegaron en modelos más pequeños (Haiku y Sonnet) trabajando como subagentes. La división no fue económica, sino deliberada: un modelo que comenzara de cero a en el código del parcheo muy plausiblemente resultaría a introducir el bug del desfase de bytes, porque la forma natural de escribir ese código es la forma incorrecta.
Los modelos delegado encontraron cuatro fallos reales in código escrito por Claude,
including one that detached the docblock from the method it documented and one
where switch statements anidados anidas soltarán ramas en silencio. Ambas
pasaron todos los controles de validación. El análisis adversario realizado por un
modelo sin ningún interés en el código fue lo único que los detectó.
Persona — revisión y aceptación. Yo dirigía la secuencia, inspeccionaba los reultados, cuestionaba las afirmaciones y decidía qué quedaba. Claude ejecutó la validación y las corridas de calibración; yo leía lo que venía y decidía lo que significaba.
Qué no aportó este proceso
Ninguna persona ha leído el, las ~7,400 líneas de este repositorio — aproximadamente 4,100 del servidor, decir 2.700 de pruebas y 600 del banco de las mediciones — línea a línea. La confianza aquí se obtiene de pruebas contrastadas con código roto a propósito, de mediciones contra un código real y de un diseño que se niega a crear nada que no pueda verificar —no de una auditoría manual.
Si ese mientras tanto no es el tipo de de confianza que quieras en una herramienta que edita tus archivos fuente, es es una postura razonable, y la sección de responsabilidad detalla lo que los controles ofrecen y lo que no.
Por qué esto está en el README
Bifrost es la demostración de sus propias afirmaciones. La contribución humana con valor no fue write teclear el código: fue definir el problema, set contexto el contexto, cuestionar el output y se insistir en las validaciones suficientes para poder confiar en las código generado.
El repositorio conserva deliberadamente el razonamiento, las ideas rechazadas, la revisión adversaria y las mediciones — incluidas las piezas donde las IA se equivocó y lo dijo.
Documentación
Documento | Qué es |
qué es, qué puede hacer, cómo instalarlo y de lo que eres | |
qué se construye y por qué | |
una revisión con una mirada nueva buscando las razones de que esto falle — doces hallazgos, dos después refutados por las mediciones | |
qué hizo realmente el worker cuando se le pidió | |
en qué lugar está junto a Aider, Serena y fast-apply — y dónde ganan ellas | |
lo que se consume, lo que se concede |
brainstorm/ es la grabación de trabajo: la especificación original, el
diario de diseño a lo largo cinco revisiones, la revisión de la revisión adversaria, y los
resultados de la calibración. docs/ es la referencia y gana cuando los dos difieren.
Responsabilidad
Esta herramienta edita tus archivos fuente de forma automática usando un modelo de lenguaje. Apache 2.0 significa que se entrega tal cual, sin garantía: el responsable de lo que haga en tu código. Lee los diffs, se ejecuta tus pruebas, despliega con intención. El manual es concreto sobre los que los controles interceptan y no interceptan.
Contribuciones
Contribuciones de toda clase bienvenidas — incluido el argumento de que algo aquí está mal. Este proyecto ya al ha elimido una puerta de validación por ser tautológica y refutado dos de sus propias afirmaciones con mediciones.
Una regla —y es la que de verdad importa—: cada prueba debe poder fallar. Detalles en el manual.
Licencia
Construido sobre el Model Context Protocol, con licencia MIT de Anthropic, PBC. MCP-Bifrost es un proyecto independiente y los no está afiliado a Anthropic, PBC, ni lo apoya ni lo patrocina.
Available Tools
11 toolscreate_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
Scored across 11 tools
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.
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.
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.
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
Related MCP Connectors
Hand tasks, bugs and finished work to AI coding agents, and get back a write-up with evidence.
Reliable async execution for agent tool calls: schema gating, retries, idempotency, audit trail.
Change-aware CI validation and affected-test guidance for coding agents.
Hosted coding agent: start, follow up on and stop tasks that can open GitHub pull requests.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables Codex to delegate bulk code reading, patching, and testing to an async worker using cheaper AI models, while receiving compact results.31 npm2MIT
- AlicenseAqualityDmaintenanceEnables coding agents to perform safe, project-wide Python refactoring (rename, move, extract, inline, change signature, organize imports, etc.) with a dry-run safety contract and LSP-coordinate addressing.15MIT
- AlicenseNot gradedqualityDmaintenanceEnables Codex to offload expensive code reading, editing, and checking to a worker agent via Claude Code, supporting async jobs and long-running tasks.MIT
- AlicenseNot gradedqualityCmaintenanceEnables delegating coding tasks to sandboxed agents, returning changes as auditable diffs for human review before applying or discarding them.1MIT