Skip to main content
Glama

replace_content

Search and replace text or regex patterns in files across specified paths. Perform multiple operations at once, with options to ignore case or use regex.

Instructions

Replace content within files across multiple specified paths.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationsYesAn array of search/replace operations to apply to each file.
pathsYesAn array of relative file paths to perform replacements on.

Implementation Reference

  • Core internal handler function that orchestrates argument parsing, file processing, and response formatting for the replace_content tool.
    export const handleReplaceContentInternal = async (
      args: unknown,
      deps: ReplaceContentDeps,
    ): Promise<McpToolResponse> => {
      // Specify output type
      const { paths: relativePaths, operations } = parseAndValidateArgs(args);
    
      const finalResults = await processAllFilesReplacement(relativePaths, operations, deps);
    
      // Return results in McpToolResponse format
      return {
        success: true,
        data: {
          results: finalResults,
        },
        content: [
          {
            type: 'text',
            text: JSON.stringify({ results: finalResults }, undefined, 2),
          },
        ],
      };
    };
  • Input schemas defining the structure for replace_content tool arguments: ReplaceOperationSchema and ReplaceContentArgsSchema.
    export const ReplaceOperationSchema = z
      .object({
        search: z.string().describe('Text or regex pattern to search for.'),
        replace: z.string().describe('Text to replace matches with.'),
        use_regex: z.boolean().optional().default(false).describe('Treat search as regex.'),
        ignore_case: z.boolean().optional().default(false).describe('Ignore case during search.'),
      })
      .strict();
    
    export const ReplaceContentArgsSchema = z
      .object({
        paths: z
          .array(z.string())
          .min(1, { message: 'Paths array cannot be empty' })
          .describe('An array of relative file paths to perform replacements on.'),
        operations: z
          .array(ReplaceOperationSchema)
          .min(1, { message: 'Operations array cannot be empty' })
          .describe('An array of search/replace operations to apply to each file.'),
      })
      .strict();
  • Tool definition for 'replace_content' including name, description, input/output schemas, and handler wrapper that provides dependencies.
    export const replaceContentToolDefinition = {
      name: 'replace_content',
      description: 'Replace content within files across multiple specified paths.',
      inputSchema: ReplaceContentArgsSchema,
      // Define output schema for better type safety and clarity
      outputSchema: z.object({
        results: z.array(
          z.object({
            file: z.string(),
            replacements: z.number().int(),
            modified: z.boolean(),
            error: z.string().optional(),
          }),
        ),
      }),
      // Use locally defined McpResponse type with proper request type
      handler: async (args: unknown): Promise<McpToolResponse> => {
        // Validate input using schema first
        const validatedArgs = ReplaceContentArgsSchema.parse(args);
        // Production handler provides real dependencies
        const productionDeps: ReplaceContentDeps = {
          readFile: fs.readFile,
          writeFile: fs.writeFile,
          stat: fs.stat,
          resolvePath: resolvePath,
        };
        return handleReplaceContentInternal(validatedArgs, productionDeps);
      },
    };
  • Import and registration of replaceContentToolDefinition into the central allToolDefinitions array used for MCP tool exposure.
    import { replaceContentToolDefinition } from './replace-content.js';
    import { handleApplyDiff } from './apply-diff.js';
    import { applyDiffInputSchema, ApplyDiffOutput } from '../schemas/apply-diff-schema.js';
    import fs from 'node:fs';
    import path from 'node:path';
    
    // Define the structure for a tool definition (used internally and for index.ts)
    import type { ZodType } from 'zod';
    import type { McpToolResponse } from '../types/mcp-types.js';
    
    // Define local interfaces based on usage observed in handlers
    // Define the structure for a tool definition
    // Matches the structure in individual tool files like applyDiff.ts
    export interface ToolDefinition<TInput = unknown, TOutput = unknown> {
      name: string;
      description: string;
      inputSchema: ZodType<TInput>;
      outputSchema?: ZodType<TOutput>;
      handler: (args: TInput) => Promise<McpToolResponse>; // Changed _args to args
    }
    
    // Helper type to extract input type from a tool definition
    export type ToolInput<T extends ToolDefinition> =
      T extends ToolDefinition<infer I, unknown> ? I : never;
    
    // Define a more specific type for our tool definitions to avoid naming conflicts
    type HandlerToolDefinition = {
      name: string;
      description: string;
      inputSchema: ZodType<unknown>;
      outputSchema?: ZodType<unknown>;
      handler: (args: unknown) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;
    };
    
    // Aggregate all tool definitions into a single array
    // Use our more specific type to avoid naming conflicts
    export const allToolDefinitions: HandlerToolDefinition[] = [
      listFilesToolDefinition,
      statItemsToolDefinition,
      readContentToolDefinition,
      writeContentToolDefinition,
      deleteItemsToolDefinition,
      createDirectoriesToolDefinition,
      chmodItemsToolDefinition,
      chownItemsToolDefinition,
      moveItemsToolDefinition,
      copyItemsToolDefinition,
      searchFilesToolDefinition,
      replaceContentToolDefinition,
  • Key helper function that processes replacements for a single file, including reading content, applying operations, writing changes, and error handling.
    async function processSingleFileReplacement(
      relativePath: string,
      operations: ReplaceOperation[],
      deps: ReplaceContentDeps,
    ): Promise<ReplaceResult> {
      const pathOutput = relativePath.replaceAll('\\', '/');
      let targetPath = '';
      let originalContent = '';
      let fileContent = '';
      let totalReplacements = 0;
      let modified = false;
    
      try {
        targetPath = await deps.resolvePath(relativePath);
        const stats = await deps.stat(targetPath);
        if (!stats.isFile()) {
          // Return specific error if path is not a file
          return {
            file: pathOutput,
            replacements: 0,
            modified: false,
            error: 'Path is not a file',
          };
        }
    
        originalContent = await deps.readFile(targetPath, 'utf8');
        fileContent = originalContent;
    
        for (const op of operations) {
          const { newContent, replacementsMade } = applyReplaceOperation(fileContent, op);
          // Only update content and count if replacements were actually made
          if (replacementsMade > 0 && newContent !== fileContent) {
            fileContent = newContent;
            totalReplacements += replacementsMade; // Accumulate replacements across operations
          }
        }
    
        // Check if content actually changed after all operations
        if (fileContent !== originalContent) {
          modified = true;
          await deps.writeFile(targetPath, fileContent, 'utf8');
        }
    
        return { file: pathOutput, replacements: totalReplacements, modified };
      } catch (error: unknown) {
        // Catch any error during the process (resolve, stat, read, write)
        const fileError = handleReplaceError(error, relativePath);
        return {
          file: pathOutput,
          replacements: totalReplacements, // Return replacements count even on write error
          modified: false,
          error: fileError, // Use the formatted error message
        };
      }
    }
Install Server

Other Tools

Related 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/SylphxAI/filesystem-mcp'

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