Bug #15: mcp_edit Ignored force:true
Status: RESOLVED in v3.14.5 Category: Tool Parity Severity: Medium (forced fallback to full file rewrite, wasted tool calls) Resolution Date: 2026-02-28
Problem
Section titled “Problem”When mcp_edit blocked an edit due to the 30% change threshold (risk assessment), the error message instructed the AI to retry with "force": true. Claude followed the instruction, but the second call was blocked with the identical error — as if force: true had never been sent.
What Happened
Section titled “What Happened”- Claude called
mcp_edit(path, old_text, new_text)to replace a large block - Server returned:
OPERATION BLOCKED - HIGH risk ... To proceed anyway, add "force": true - Claude called
mcp_edit(path, old_text, new_text, force=true) - Server returned the same block error
- Claude fell back to
mcp_write(full file rewrite) as a workaround
Root Cause
Section titled “Root Cause”mcp_edit is a convenience alias for edit_file, registered separately in main.go. When it was created, the force parameter was omitted:
- Schema: The tool definition did not include
mcp.WithBoolean("force", ...), so the MCP protocol never advertised the parameter to clients - Handler: The handler hardcoded
falseas the force argument toEditFile():result, err := engine.EditFile(path, oldText, newText, false)
The original edit_file tool had both the schema declaration and the args["force"].(bool) extraction working correctly. The alias simply was never given them.
Why It Matters
Section titled “Why It Matters”- The AI client follows the error message’s instructions exactly, but gets punished for it
- Every blocked edit wastes 2 tool calls instead of 1 (the retry that can never succeed)
- The fallback to
mcp_writeloses surgical edit semantics (backup, risk tracking, match confidence)
Solution
Section titled “Solution”Added the force parameter to mcp_edit at both levels:
Tool schema — declares the parameter so AI clients can discover and use it:
mcp.WithBoolean("force", mcp.Description("Force operation even if HIGH/CRITICAL risk (default: false)")),Handler — extracts the value from request arguments:
args := request.GetArguments()force := falseif args != nil { if f, ok := args["force"].(bool); ok { force = f }}result, err := engine.EditFile(path, oldText, newText, force)This matches the pattern used by edit_file, intelligent_edit, and auto_recovery_edit.
Security
Section titled “Security”The risk assessment system was unchanged at time of this fix (v3.14.5). Note: As of v3.15.1 (Bug #16), the risk model was updated — only CRITICAL (>=90%) blocks; MEDIUM and HIGH auto-proceed with backup + warning.
Files Changed
Section titled “Files Changed”| File | Change |
|---|---|
main.go | Added force parameter to mcp_edit schema and handler |
Testing
Section titled “Testing”- Build:
go buildpasses - Tests:
go test ./tests/... ./core/...all pass - Manual: Confirmed
mcp_editwithforce: truebypasses risk block; withoutforce, behavior unchanged