How to Use `edit_block` for Precise Text Replacement in DesktopCommanderMCP

The edit_block tool lets you make exact text changes in files by specifying an old_string/new_string pair or a range/content pair, with built-in safety checks and atomic editing that preserves surrounding content.

DesktopCommanderMCP exposes the edit_block tool as a safer alternative to full-file rewrites. Whether you're swapping a line in a shell script or updating a specific cell in an Excel workbook, this tool minimizes collateral damage by touching only the matched text.

Understanding the edit_block Architecture

The tool is implemented across several modules in the wonderwhy-er/DesktopCommanderMCP repository. Each layer enforces correctness and provides clear feedback when operations fail.

Tool Registration and Schema Validation

In src/server.ts (lines 812-854), edit_block is registered as a JSON-RPC tool with a detailed description:

"Make a targeted edit to a file using the edit_block tool. This tool applies a single block of text replacement to a file. It is safer than write_file because it only modifies the specified text block... Make separate edit_block calls for each distinct change."

The Zod schema in src/tools/schemas.ts (lines 148-168) validates that exactly one editing mode is selected:

  • Text replacement mode requires old_string and new_string
  • Range mode requires range and content (for structured files like Excel)

If you provide neither mode or mix parameters incorrectly, validation fails before any file is touched.

Execution Flow in edit.ts

The dispatcher logic in src/tools/edit.ts (lines 391-465) routes requests based on file type:

File Type Handler Location
Plain text performSearchReplace src/tools/edit.ts#L116-L204
Excel (.xlsx) ExcelFileHandler.editRange src/utils/files/excel.ts#L160-L237
DOCX (.docx) DocxFileHandler.editRange (or XML search) src/utils/files/docx.ts#L229-L242

If range is supplied for a file type that doesn't support range editing, the tool returns: "Range-based editing not supported for [file_type]" (line 460).

Text Replacement Mode: old_string and new_string

For most files, performSearchReplace scans the entire document and replaces occurrences of old_string with new_string.

Safety Parameter: expected_replacements

This parameter (default: 1) guards against accidental multi-line changes. In src/tools/edit.ts (line 243), when the actual count differs from the expectation, the tool returns warning code server_edit_block_unexpected_count but still applies the edit.

Example: Precision Edit in a Configuration File

await callTool('edit_block', {
  file_path: '/app/config.yml',
  old_string: 'timeout: 30s',
  new_string: 'timeout: 120s',
  expected_replacements: 1
});

The server returns a ServerResult containing:

  • editsApplied: number of successful replacements
  • Warning flags if expectations weren't met

Range Mode: range and content

Structured files expose editRange for coordinate-based editing.

Excel: Cell-Level Updates

In src/utils/files/excel.ts (line 63), the range syntax follows standard spreadsheet notation (SheetName!CellReference).

await callTool('edit_block', {
  file_path: '/data/financials.xlsx',
  range: 'Q3!B4',
  content: [[ 154000 ]],
  expected_replacements: 1
});

The content parameter is a 2-D array: each inner array represents a row. To update a 3×2 block starting at B4:

content: [
  [100, 200],    // B4, C4
  [300, 400],    // B5, C5
  [500, 600]     // B6, C6
]

DOCX: XML Fragment Replacement

For Word documents, you can edit the underlying XML directly. From src/utils/files/docx.ts (lines 229-242), the handler unzips the .docx, locates the target XML, and applies the replacement.

await callTool('edit_block', {
  file_path: '/contracts/agreement.docx',
  old_string: '<w:t>Initial Payment: $5,000</w:t>',
  new_string: '<w:t>Initial Payment: $7,500</w:t>',
  expected_replacements: 1
});

As documented in src/server.ts (line 854), you should make separate edit_block calls for each distinct change. This improves auditability and error isolation.

await Promise.all([
  callTool('edit_block', {
    file_path: '/scripts/deploy.sh',
    old_string: 'docker build -t app:latest .',
    new_string: 'docker build -t app:v1.2.0 .',
    expected_replacements: 1
  }),
  callTool('edit_block', {
    file_path: '/scripts/deploy.sh',
    old_string: 'docker run -p 8080:8080 app:latest',
    new_string: 'docker run -p 8080:8080 --restart unless-stopped app:v1.2.0',
    expected_replacements: 1
  })
]);

Each call is logged independently with telemetry codes like server_edit_block_exact_success, enabling precise debugging in production workflows.

Error Handling and UI Integration

When edit_block fails, src/ui/file-preview/src/payload-utils.ts (lines 102-121) transforms server responses into actionable error messages. Common failure modes include:

  • Exact match not found: old_string doesn't appear in the file
  • Unexpected replacement count: expected_replacements was 1 but 3 matches found
  • File type mismatch: range provided for unsupported format

The UI layer in src/ui/file-preview/src/markdown/controller.ts (line 829) automatically splits user edits into minimal edit_block payloads, ensuring LLM-driven workflows stay within safe operational bounds.

Summary

  • edit_block performs atomic text replacement using either old_string/new_string or range/content
  • Registration: src/server.ts#L812-L854 defines the tool schema and usage constraints
  • Validation: src/tools/schemas.ts#L148-L168 enforces mutually exclusive parameter sets
  • Dispatch: src/tools/edit.ts#L391-L465 routes to appropriate handlers based on file type
  • Text engine: src/tools/edit.ts#L116-L204 implements performSearchReplace with expected_replacements safety checks
  • Excel handler: src/utils/files/excel.ts#L160-L237 supports Sheet!Cell range syntax with 2-D array content
  • DOCX handler: src/utils/files/docx.ts#L229-L242 enables XML-level precision editing
  • One edit_block call per logical change is the enforced best practice for reliability and telemetry clarity

Frequently Asked Questions

What happens if old_string appears multiple times in a file?

By default, expected_replacements is 1. If your old_string appears more than once, the tool still performs replacements but returns warning server_edit_block_unexpected_count. Set expected_replacements to the actual count to suppress this warning, or scope your old_string with additional surrounding context to make it unique.

Can I use edit_block on binary files like PDFs?

DesktopCommanderMCP does not implement editRange for PDF files. Providing range to a PDF returns "Range-based editing not supported for pdf" from src/tools/edit.ts line 460. For PDF modifications, use the read_file tool to extract text, then write_file or external tools.

Why does the tool require expected_replacements?

This parameter prevents silent bulk changes. In automated LLM workflows, a model might accidentally match a generic string like "return" dozens of times. The default expectation of 1 replacement forces explicit acknowledgment when multiple matches exist, catching logic errors before they propagate.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →