Skip to main content
Glama
arathald

mcp-editor

by arathald

string_replace

Replace text in files by specifying the old string and new string, enabling content updates without manual editing.

Instructions

Replace a string in a file with a new string

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to the file
old_strYesString to replace
new_strNoReplacement string (empty string if omitted)

Implementation Reference

  • The strReplace method in the FileEditor class executes the string_replace tool: validates the path, reads the file, ensures exactly one occurrence of old_str, replaces it with new_str, updates the file and history, and returns a contextual snippet of the change.
    async strReplace(args: StringReplaceArgs): Promise<string> {
        await validatePath('string_replace', args.path);
    
        const fileContent = await readFile(args.path);
        const oldStr = args.old_str.replace(/\t/g, '    ');
        const newStr = args.new_str?.replace(/\t/g, '    ') ?? '';
    
        const occurrences = fileContent.split(oldStr).length - 1;
        if (occurrences === 0) {
            throw new ToolError(
                `No replacement was performed, old_str \`${args.old_str}\` did not appear verbatim in ${args.path}.`
            );
        }
    
        if (occurrences > 1) {
            const lines = fileContent.split('\n')
                .map((line, idx) => line.includes(oldStr) ? idx + 1 : null)
                .filter((idx): idx is number => idx !== null);
    
            throw new ToolError(
                `No replacement was performed. Multiple occurrences of old_str \`${args.old_str}\` in lines ${lines}. Please ensure it is unique`
            );
        }
    
        const newContent = fileContent.replace(oldStr, newStr);
        await writeFile(args.path, newContent);
    
        if (!this.fileHistory[args.path]) {
            this.fileHistory[args.path] = [];
        }
        this.fileHistory[args.path].push(fileContent);
    
        const replacementLine = fileContent.split(oldStr)[0].split('\n').length;
        const startLine = Math.max(0, replacementLine - SNIPPET_LINES);
        const endLine = replacementLine + SNIPPET_LINES + newStr.split('\n').length;
        const snippet = newContent.split('\n').slice(startLine, endLine + 1).join('\n');
    
        let successMsg = `The file ${args.path} has been edited. `;
        successMsg += makeOutput(snippet, `a snippet of ${args.path}`, startLine + 1);
        successMsg += 'Review the changes and make sure they are as expected. Edit the file again if necessary.';
    
        return successMsg;
    }
  • src/server.ts:81-102 (registration)
    Registers the string_replace tool in the list of tools provided by the MCP server, including its name, description, and input schema.
    {
        name: "string_replace",
        description: "Replace a string in a file with a new string",
        inputSchema: {
            type: "object",
            properties: {
                path: {
                    type: "string",
                    description: "Absolute path to the file"
                },
                old_str: {
                    type: "string",
                    description: "String to replace"
                },
                new_str: {
                    type: "string",
                    description: "Replacement string (empty string if omitted)"
                }
            },
            required: ["path", "old_str"]
        }
    },
  • src/server.ts:162-166 (registration)
    Dispatches calls to the string_replace tool by validating arguments with isStrReplaceArgs and invoking the editor's strReplace method.
    case "string_replace":
        if (!request.params.arguments || !isStrReplaceArgs(request.params.arguments)) {
            throw new ToolError("Invalid arguments for string_replace command");  // Fixed
        }
        result = await this.editor.strReplace(request.params.arguments);
  • TypeScript interface defining the input arguments for the string_replace tool.
    export interface StringReplaceArgs extends Record<string, unknown> {
        path: string;
        old_str: string;
        new_str?: string;
    }
  • Type guard function for validating string_replace arguments at runtime.
    export function isStrReplaceArgs(args: Record<string, unknown>): args is StringReplaceArgs {
        return typeof args.path === "string" &&
            typeof args.old_str === "string" &&
            (args.new_str === undefined || typeof args.new_str === "string");
    }
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the action ('Replace a string in a file') but doesn't mention critical behaviors such as whether the operation is destructive, requires file permissions, handles errors (e.g., if the string isn't found), or affects file encoding. This leaves significant gaps for safe and effective use.

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 a single, clear sentence with zero wasted words. It's front-loaded with the core action and resource, making it highly efficient and easy to parse for an AI agent.

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

Completeness2/5

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

Given the tool's complexity (a file mutation operation) and the lack of annotations and output schema, the description is insufficient. It doesn't cover behavioral aspects like safety, error handling, or output format, which are crucial for a tool that modifies files. This leaves the agent with incomplete context for reliable use.

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 input schema has 100% description coverage, clearly documenting all three parameters (path, old_str, new_str). The description adds no additional meaning beyond what the schema provides, such as examples or edge cases (e.g., handling empty strings or special characters). Thus, it meets the baseline score when schema coverage is high.

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

Purpose4/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 a specific verb ('Replace') and resource ('a string in a file'), making it immediately understandable. However, it doesn't differentiate from sibling tools like 'insert' or 'undo_edit', which might also modify files, so it doesn't reach the highest score.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'insert' or 'undo_edit'. It lacks context about scenarios where string replacement is preferred over other editing operations, leaving the agent to infer usage from the tool name alone.

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/arathald/mcp-editor'

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