Efficient Code Editing
Overview
Section titled “Overview”This guide shows how to use MCP Filesystem Ultra tools efficiently to minimize token usage when editing code. Reading and writing only the parts you need usually saves a large fraction of tokens compared to full-file round-trips.
The Problem: Token Waste
Section titled “The Problem: Token Waste”AI assistants sometimes read entire files and rewrite them completely, even when the change is only a few lines. For a 5,000-line file, that means sending thousands of lines of context on every turn.
Optimal Workflow for Small Changes
Section titled “Optimal Workflow for Small Changes”When you need to edit a specific function or section:
Step 1: Locate the code
Section titled “Step 1: Locate the code”search_files(path="engine.go", pattern="func ReadFile")Result: file path, line number, and matching line.
Step 2: Read only that section
Section titled “Step 2: Read only that section”read_file(path="engine.go", start_line=45, end_line=67)Result: exactly the lines you need.
Step 3: Apply targeted edits
Section titled “Step 3: Apply targeted edits”edit_file(path="engine.go", old_text="return nil", new_text="return content")For several changes in the same file, use multi_edit so the file is written once and the diff is returned as a single result.
Optimal Workflow for Large Files
Section titled “Optimal Workflow for Large Files”For large files, prefer a targeted workflow:
- Use
search_files()to locate the relevant lines. - Use
read_file()withstart_line/end_lineto read only those lines. - Edit with
edit_file()ormulti_edit()using the exact text from the read.
Example:
- File size: 5,000 lines
- Read-only approach:
read_file()returns the whole file. - Targeted approach:
search_files()+read_file(start_line/end_line)+edit_file()touches only the needed lines.
The savings grow with file size; the exact amount depends on your model and token pricing.
Antipatterns to Avoid
Section titled “Antipatterns to Avoid”| Antipattern | Problem | Better Way |
|---|---|---|
read_file() on a large file when you only need a section | Sends unnecessary context | Use read_file() with start_line/end_line |
| Edit without locating the target first | Risk of wrong replacement or stale context | Use search_files() first to verify location |
Many sequential edit_file() calls on the same file | Multiple disk writes and re-reads | Use multi_edit() for several changes in one atomic write |
| Rewriting an entire file for a small change | Sends the whole file back and forth | Use edit_file() for surgical changes |
Tools Quick Reference
Section titled “Tools Quick Reference”| Tool | Purpose | Use When |
|---|---|---|
search_files | Find code location | You need to locate where something is |
read_file with start_line/end_line | Read lines N–M | You know the line numbers (from search) |
read_file | Read entire file | File is small, or you genuinely need the whole file |
edit_file | Replace text in file | You have exact old_text and new_text |
multi_edit | Multiple edits in one file | You have several changes in the same file |
write_file | Create/overwrite entire file | File does not exist or needs a complete rewrite |
search_files with count_only:true | Count matches without reading | You need to verify how many occurrences exist |
edit_file with occurrence | Replace a specific match | You need to change only the 1st, 2nd, or last occurrence |
Real Example: Refactoring a Function
Section titled “Real Example: Refactoring a Function”Scenario: Change ProcessData() in a large file.
Bad approach
Section titled “Bad approach”read_file("main.go")— reads the entire file.- Analyze and rewrite.
write_file("main.go", entire_content)— writes the entire file back.
Good approach
Section titled “Good approach”search_files("main.go", "func ProcessData")— returns the line range.read_file("main.go", start_line=156, end_line=189)— reads only the function.edit_file("main.go", old_snippet, new_snippet)— replaces the changed lines.
If you need to change several places inside that function, use multi_edit instead.
Concurrency and External Changes
Section titled “Concurrency and External Changes”For edits that depend on a previous read, use expected_hash to detect external changes:
read_file()returns acontent_hash.- Feed that hash to the next
edit_file(expected_hash: ...). - If the file changed on disk in between, the edit fails with a clear
external_changewarning.
This prevents accidental overwrites when another process (or another agent) touched the file.
Pipeline Workflows
Section titled “Pipeline Workflows”For multi-file operations, batch_operations with a pipeline_json can chain search, read, edit, and verify steps in one call.
Pattern: Search → Edit → Verify
Section titled “Pattern: Search → Edit → Verify”{ "name": "rename-function", "create_backup": true, "steps": [ { "id": "find", "action": "search", "params": { "path": "src/", "pattern": "oldFunc" } }, { "id": "edit", "action": "edit", "input_from": "find", "params": { "old_text": "oldFunc", "new_text": "newFunc" } }, { "id": "verify", "action": "count_occurrences", "input_from": "find", "params": { "pattern": "newFunc" } } ]}This is one round-trip instead of three separate calls, and it includes automatic backup and rollback.
Pattern: Dry-Run Before Commit
Section titled “Pattern: Dry-Run Before Commit”Preview changes without modifying files:
{ "name": "preview-migration", "dry_run": true, "verbose": true, "steps": [ { "id": "find", "action": "search", "params": { "path": ".", "pattern": "deprecated_api", "file_types": [".go"] } }, { "id": "preview", "action": "edit", "input_from": "find", "params": { "old_text": "deprecated_api", "new_text": "new_api" } } ]}Shows which files would be affected and how many replacements, without touching disk.
Summary
Section titled “Summary”- Search first — use
search_filesto find line numbers. - Read ranges — use
read_filewithstart_line/end_linewhen you only need part of a file. - Edit surgically — prefer
edit_fileoverwrite_filefor small changes. - Batch same-file edits — use
multi_editfor multiple changes in one file. - Chain multi-file work — use
batch_operationswithpipeline_jsonwhen possible. - Verify external changes — use
expected_hashto chain reads and edits safely.
Following these patterns usually saves a large fraction of tokens compared to full-file round-trips, and it reduces the chance of accidental overwrites.