An MCP server that delegates mechanical code edits to a cheap worker model, validates them through a chain of gates, and applies them atomically.
MCP-Bifrost demonstrates strong naming conventions (verb-first: fix_*, insert_*, create_*, publish, report) and comprehensive descriptions (avg 250+ chars, well above 194-char baseline). All 8 tools have detailed, LLM-optimized descriptions explaining WHEN to use each tool and what it does. Input schemas are present and typed for all tools. However, several parameters lack descriptions (e.g., 'targets' items in fix_symbols has no field-level schema; 'context' arrays lack item descriptions), and output schemas are entirely undocumented. Error handling guidance is minimal, no recovery hints or categorization. The server excels at composition (tools chain well via file_path/symbol_name references) and security awareness (allow_secrets gate, verify command validation), but falls short on output documentation and error recovery patterns.
Create a new source file from scratch. The worker sees the directory structure and neighbouring files as context, so the new file matches the codebase style. The file must not already exist — create_file never overwrites.
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.
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.
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.
Output schemas completely undocumented. No tool describes what it returns, field types, or structure. LLMs cannot plan downstream calls or extract results reliably.
Parameter 'targets' in fix_symbols has type 'array' with items type 'object', but no field-level schema for 'file_path', 'symbol_name', or 'instruction'. LLMs cannot infer required vs optional fields or types.
No error handling guidance. Tools do not describe what errors are retryable, user-fixable, or fatal. No recovery hints (e.g., 'If symbol not found, call report() to list available symbols').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
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.
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.
Commit all pending patches and generate a changelog. Reads the operational log, generates documentation, and commits the changes with a message derived from the patches applied.
Generate a report from the operational log without committing. Shows what patches were applied, their rationale, and statistics.
'context' parameter in fix_symbol, fix_range, insert_symbol, insert_case is array of strings with no item description. Unclear what format or content is expected.
No confirmation or dry-run pattern for destructive operations (fix_symbol, fix_range, publish all modify code). Agents cannot preview changes before committing.