Skip to content

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

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.

  1. Claude called mcp_edit(path, old_text, new_text) to replace a large block
  2. Server returned: OPERATION BLOCKED - HIGH risk ... To proceed anyway, add "force": true
  3. Claude called mcp_edit(path, old_text, new_text, force=true)
  4. Server returned the same block error
  5. Claude fell back to mcp_write (full file rewrite) as a workaround

mcp_edit is a convenience alias for edit_file, registered separately in main.go. When it was created, the force parameter was omitted:

  1. Schema: The tool definition did not include mcp.WithBoolean("force", ...), so the MCP protocol never advertised the parameter to clients
  2. Handler: The handler hardcoded false as the force argument to EditFile():
    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.

  • 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_write loses surgical edit semantics (backup, risk tracking, match confidence)

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 := false
if 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.

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.

FileChange
main.goAdded force parameter to mcp_edit schema and handler
  • Build: go build passes
  • Tests: go test ./tests/... ./core/... all pass
  • Manual: Confirmed mcp_edit with force: true bypasses risk block; without force, behavior unchanged