How the Desktop Commander MCP Edit Block Tool Handles Replacing Multiple Text Instances

The Desktop Commander MCP edit_block tool replaces multiple text instances only when you explicitly declare the expected match count via the expected_replacements parameter, defaulting to a single replacement for safety.

The edit_block tool (often called the "surgical-edit" capability) provides exact-string find-and-replace functionality within the Desktop Commander MCP server. This article explains the multi-occurrence replacement mechanism, the safety guardrails that prevent accidental bulk edits, and how to correctly invoke replacements across multiple matches.

The expected_replacements Parameter Design

The core safety mechanism centers on the expected_replacements parameter, defined in src/tools/schemas.ts at line 153. By default, this value is set to 1, which means the tool will reject any file containing more than one match for the search string.

This design prevents ambiguous edits where a developer might unintentionally replace every occurrence of a common string like " " or "return" throughout an entire file.

How Match Counting Works

When edit_block executes, the performSearchReplace function (implemented in src/tools/edit.ts) performs the following validation sequence:

  1. Scan the target file for all instances of old_string
  2. Record the actual match count
  3. Compare against the supplied expected_replacements value
  4. Proceed only if counts match exactly

If the actual count exceeds the expected count, the tool emits a warning at line 248 of src/tools/edit.ts:

"Double-check and make sure you understand all occurrences and if you want to replace all count occurrences, set expected_replacements to count."

This warning appears as a soft failure — the file remains unmodified, giving you opportunity to confirm the intended scope.

Replacing Multiple Instances: Code Examples

Single Replacement (Default Behavior)

// Succeeds only if exactly one "TODO" exists in the file
await callTool('edit_block', {
  path: 'src/app.js',
  old_string: 'TODO',
  new_string: 'DONE'
});

When expected_replacements is omitted, the schema default of 1 applies. The edit aborts with a warning if zero or multiple matches exist.

Explicit Multiple Replacements

// Replace exactly three occurrences — no more, no less
await callTool('edit_block', {
  path: 'src/app.js',
  old_string: 'VERSION = "1.0.0"',
  new_string: 'VERSION = "2.0.0"',
  expected_replacements: 3
});

Success is recorded via the server_edit_block_exact_success telemetry capture at line 204 of src/tools/edit.ts.

Mismatch Detection

// WARNING: file contains two "DEBUG" strings but we expect one
await callTool('edit_block', {
  path: 'src/app.js',
  old_string: 'DEBUG',
  new_string: 'TRACE',
  expected_replacements: 1
});

This invocation fails with a warning because the actual count (2) exceeds the declared expectation (1).

Server-Side API Documentation

The tool definition in src/server.ts (lines 847-850) documents expected_replacements as an optional integer parameter. According to the Desktop Commander MCP source code, this parameter exists specifically to enable "multi-occurrence edits" while maintaining the protective default of single-target replacement.

Safety Trade-offs

Approach Risk Level Use Case
Default (expected_replacements: 1) Low Confident single-target edits
Explicit count match Medium Deliberate batch updates
No validation (hypothetical) High Not implemented — protected by design

The tool deliberately does not provide a "replace all" wildcard. You must know and declare your target count, forcing conscious acknowledgment of edit scope.

Summary

  • expected_replacements defaults to 1 in src/tools/schemas.ts
  • Match counting occurs in performSearchReplace within src/tools/edit.ts
  • Exact count match required — no partial replacement permitted
  • Warning messages guide users to correct their declaration when counts mismatch
  • Success telemetry captured at line 204 via server_edit_block_exact_success
  • API documented in src/server.ts with explicit safety rationale

Frequently Asked Questions

What happens if I don't specify expected_replacements?

The tool uses the default value of 1 from the Zod schema in src/tools/schemas.ts. Your edit succeeds only if exactly one match exists; otherwise, you receive a warning explaining the actual match count found.

Can I use edit_block to replace all occurrences without knowing the count?

No. The Desktop Commander MCP source code intentionally requires an explicit count. You must first determine how many matches exist — perhaps via a search tool — then supply that number as expected_replacements. This prevents accidental mass replacements.

Why does the tool abort rather than replacing fewer matches?

The validation logic in src/tools/edit.ts enforces an all-or-nothing policy. If your declared expectation doesn't match reality, the entire edit is cancelled. This atomic behavior ensures files never reach a partially-edited, inconsistent state.

Where is the replacement logic implemented?

The performSearchReplace function in src/tools/edit.ts contains the core implementation. Warning generation occurs at line 248, success telemetry at line 204, and the Zod schema definition (including the default value) resides in src/tools/schemas.ts at line 153.

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 →