Skip to main content
Glama

edit_file

Surgically edit files by finding and replacing exact text, ensuring precise modifications for revenue tracking and business management workflows.

Instructions

Surgically edit a file by finding and replacing exact text. 50% more efficient than read+write. Use after read_file to ensure exact match. Errors if text not found or appears multiple times. Creates backup automatically.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesFull file path
findYesExact text to find (must match exactly including whitespace)
replace_withYesText to replace it with

Implementation Reference

  • Main execution logic for edit_file tool: validates path, checks file existence, ensures unique find text match, creates backup, performs string replacement, and returns detailed change info.
    case "edit_file": {
      const { path, find, replace_with } = args;
      
      if (!isPathAllowed(path)) {
        throw new Error(`Access denied: Path not in allowed directories`);
      }
    
      if (!fs.existsSync(path)) {
        throw new Error(`File not found: ${path}`);
      }
    
      // Read current content
      const content = fs.readFileSync(path, 'utf8');
      const lines = content.split('\n');
      
      // Count occurrences
      const occurrences = (content.match(new RegExp(find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')) || []).length;
      
      if (occurrences === 0) {
        throw new Error(`Text not found in file. Search text: "${find.substring(0, 100)}..."`);
      }
      
      if (occurrences > 1) {
        throw new Error(`Text appears ${occurrences} times in file. Must be unique for safety. Search text: "${find.substring(0, 100)}..."`);
      }
    
      // Find the line numbers where the change occurs
      const findLines = find.split('\n');
      const changedLines = [];
      let foundAtLine = -1;
      
      for (let i = 0; i < lines.length; i++) {
        if (lines[i].includes(findLines[0])) {
          // Check if this is the full match
          let isMatch = true;
          for (let j = 0; j < findLines.length; j++) {
            if (i + j >= lines.length || !lines[i + j].includes(findLines[j])) {
              isMatch = false;
              break;
            }
          }
          if (isMatch) {
            foundAtLine = i + 1; // 1-indexed for humans
            for (let j = 0; j < findLines.length; j++) {
              changedLines.push(i + j + 1);
            }
            break;
          }
        }
      }
    
      // Create backup
      const backupPath = `${path}.backup-${Date.now()}`;
      fs.copyFileSync(path, backupPath);
      debugLog(`Created backup: ${backupPath}`);
    
      // Perform replacement
      const newContent = content.replace(find, replace_with);
      fs.writeFileSync(path, newContent, 'utf8');
    
      result = {
        success: true,
        path: path,
        changes: {
          linesModified: changedLines,
          totalLines: changedLines.length,
          startLine: changedLines[0],
          endLine: changedLines[changedLines.length - 1],
          before: find.substring(0, 200) + (find.length > 200 ? '...' : ''),
          after: replace_with.substring(0, 200) + (replace_with.length > 200 ? '...' : ''),
        },
        backupCreated: backupPath,
        message: `Successfully edited ${changedLines.length} line(s) at lines ${changedLines.join(', ')}`
      };
      break;
    }
  • index.js:555-576 (registration)
    Tool registration in ListTools handler, including name, description, and input schema definition.
    {
      name: "edit_file",
      description: "Surgically edit a file by finding and replacing exact text. 50% more efficient than read+write. Use after read_file to ensure exact match. Errors if text not found or appears multiple times. Creates backup automatically.",
      inputSchema: {
        type: "object",
        properties: {
          path: { 
            type: "string", 
            description: "Full file path" 
          },
          find: {
            type: "string",
            description: "Exact text to find (must match exactly including whitespace)"
          },
          replace_with: {
            type: "string",
            description: "Text to replace it with"
          }
        },
        required: ["path", "find", "replace_with"]
      }
    },
  • Input schema defining parameters for the edit_file tool: path, find, replace_with.
    inputSchema: {
      type: "object",
      properties: {
        path: { 
          type: "string", 
          description: "Full file path" 
        },
        find: {
          type: "string",
          description: "Exact text to find (must match exactly including whitespace)"
        },
        replace_with: {
          type: "string",
          description: "Text to replace it with"
        }
      },
      required: ["path", "find", "replace_with"]
    }
  • Helper function to validate if a file path is within allowed directories, used in edit_file handler for security.
    function isPathAllowed(filePath) {
      const normalized = filePath.replace(/\//g, '\\');
      return ALLOWED_PATHS.some(allowedPath => 
        normalized.startsWith(allowedPath)
      );
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does so effectively: it discloses error conditions ('Errors if text not found or appears multiple times'), efficiency claims ('50% more efficient'), and safety features ('Creates backup automatically'), offering clear behavioral context beyond basic functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is highly concise and front-loaded: it starts with the core action ('Surgically edit a file'), followed by efficiency, usage tip, error conditions, and backup feature—each sentence adds essential information with zero waste, making it easy for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description provides strong context for a mutation tool: it covers purpose, usage, errors, and safety. However, it lacks details on return values or specific error formats, leaving a minor gap in completeness for agent invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the input schema already documents all parameters well. The description adds minimal value by implying the 'find' parameter requires exact matches, but this is largely redundant with the schema's description. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('surgically edit', 'find and replace exact text') and resource ('a file'), distinguishing it from sibling tools like read_file and write_file by emphasizing its specialized text replacement functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: 'Use after read_file to ensure exact match' specifies a prerequisite, and it implicitly contrasts with alternatives like write_file by noting '50% more efficient than read+write', helping the agent choose this tool for targeted edits over broader file operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PromptishOperations/mcpSpec'

If you have feedback or need assistance with the MCP directory API, please join our Discord server