Skip to main content
Glama

Code Refactor

code_refactor

Automate code refactoring by replacing specific search patterns with defined replacement patterns using regex. Optional context and file patterns limit scope, while capture groups and matched text inclusion enhance precision.

Instructions

Refactor code by replacing search pattern with replace pattern using regex

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
context_patternNoOptional context pattern to filter matches
file_patternNoOptional file glob pattern to limit search scope
include_capture_groupsNoInclude capture groups in the results
include_matched_textNoInclude matched text in the results
replace_patternYesReplacement pattern (can use $1, $2, etc. for capture groups)
search_patternYesRegular expression pattern to search for

Implementation Reference

  • Core handler function that executes the refactoring: finds files matching pattern, applies regex search/replace (with optional context filter), tracks matches and capture groups, writes changes unless dry-run, returns results.
    export async function performRefactor(
      options: RefactorOptions
    ): Promise<RefactorResult[]> {
      const files = await searchFiles(options.filePattern);
      const results: RefactorResult[] = [];
    
      for (const filePath of files) {
        if (!existsSync(filePath)) continue;
    
        const content = readFileContent(filePath);
        const lines = content.split('\n');
        let modified = false;
        let fileReplacements = 0;
        const matchedLines: RefactorMatch[] = [];
    
        const searchRegex = new RegExp(options.searchPattern, 'g');
        const contextRegex = options.contextPattern
          ? new RegExp(options.contextPattern, 'g')
          : null;
    
        let newContent = content;
    
        if (contextRegex) {
          const matches = [...content.matchAll(searchRegex)];
          for (const match of matches) {
            if (match.index !== undefined) {
              const beforeMatch = content.substring(0, match.index);
              const afterMatch = content.substring(match.index + match[0].length);
              const contextBefore = beforeMatch.split('\n').slice(-5).join('\n');
              const contextAfter = afterMatch.split('\n').slice(0, 5).join('\n');
              const contextArea = contextBefore + match[0] + contextAfter;
    
              if (contextRegex.test(contextArea)) {
                const lineNumber = beforeMatch.split('\n').length;
                const originalLine = lines[lineNumber - 1];
    
                // Extract capture groups if any
                const captureGroups = match
                  .slice(1)
                  .filter(group => group !== undefined);
    
                const replaced = match[0].replace(
                  new RegExp(options.searchPattern),
                  options.replacePattern
                );
    
                matchedLines.push({
                  line: lineNumber,
                  content: originalLine,
                  original: match[0],
                  replaced,
                  captureGroups:
                    captureGroups.length > 0 ? captureGroups : undefined,
                });
    
                newContent = newContent.replace(match[0], replaced);
                fileReplacements++;
                modified = true;
              }
            }
          }
        } else {
          const matches = [...content.matchAll(searchRegex)];
          for (const match of matches) {
            if (match.index !== undefined) {
              const beforeMatch = content.substring(0, match.index);
              const lineNumber = beforeMatch.split('\n').length;
              const originalLine = lines[lineNumber - 1];
    
              // Extract capture groups if any
              const captureGroups = match
                .slice(1)
                .filter(group => group !== undefined);
    
              const replaced = match[0].replace(
                new RegExp(options.searchPattern),
                options.replacePattern
              );
    
              matchedLines.push({
                line: lineNumber,
                content: originalLine,
                original: match[0],
                replaced,
                captureGroups: captureGroups.length > 0 ? captureGroups : undefined,
              });
            }
          }
    
          const replacedContent = content.replace(
            searchRegex,
            options.replacePattern
          );
          if (replacedContent !== content) {
            newContent = replacedContent;
            fileReplacements = (content.match(searchRegex) || []).length;
            modified = true;
          }
        }
    
        if (modified) {
          if (!options.dryRun) {
            writeFileContent(filePath, newContent);
          }
    
          results.push({
            filePath,
            replacements: fileReplacements,
            matches: matchedLines,
            modified: true,
          });
        }
      }
    
      return results;
    }
  • Zod-based input schema defining parameters for the code_refactor tool: search_pattern, replace_pattern, context_pattern, file_pattern, include_capture_groups, include_matched_text.
    inputSchema: {
      search_pattern: z
        .string()
        .describe('Regular expression pattern to search for'),
      replace_pattern: z
        .string()
        .describe(
          'Replacement pattern (can use $1, $2, etc. for capture groups)'
        ),
      context_pattern: z
        .string()
        .optional()
        .describe('Optional context pattern to filter matches'),
      file_pattern: z
        .string()
        .optional()
        .describe('Optional file glob pattern to limit search scope'),
      include_capture_groups: z
        .boolean()
        .optional()
        .describe('Include capture groups in the results'),
      include_matched_text: z
        .boolean()
        .optional()
        .describe('Include matched text in the results'),
    },
  • src/server.ts:240-306 (registration)
    MCP server registration of the 'code_refactor' tool, including schema and thin wrapper async handler that invokes performRefactor and formats results.
    server.registerTool(
      'code_refactor',
      {
        title: 'Code Refactor',
        description:
          'Refactor code by replacing search pattern with replace pattern using regex',
        inputSchema: {
          search_pattern: z
            .string()
            .describe('Regular expression pattern to search for'),
          replace_pattern: z
            .string()
            .describe(
              'Replacement pattern (can use $1, $2, etc. for capture groups)'
            ),
          context_pattern: z
            .string()
            .optional()
            .describe('Optional context pattern to filter matches'),
          file_pattern: z
            .string()
            .optional()
            .describe('Optional file glob pattern to limit search scope'),
          include_capture_groups: z
            .boolean()
            .optional()
            .describe('Include capture groups in the results'),
          include_matched_text: z
            .boolean()
            .optional()
            .describe('Include matched text in the results'),
        },
      },
      async ({
        search_pattern,
        replace_pattern,
        context_pattern,
        file_pattern,
        include_capture_groups,
        include_matched_text,
      }) => {
        try {
          const results = await performRefactor({
            searchPattern: search_pattern,
            replacePattern: replace_pattern,
            contextPattern: context_pattern,
            filePattern: file_pattern,
            dryRun: false,
          });
    
          const summary = formatRefactorResults(results, {
            includeCaptureGroups: include_capture_groups,
            includeMatchedText: include_matched_text,
            dryRun: false,
          });
    
          return {
            content: [{ type: 'text', text: summary }],
          };
        } catch (error) {
          return {
            content: [{ type: 'text', text: `Error during refactoring: ${error}` }],
            isError: true,
          };
        }
      }
    );
  • Helper function to format refactor results into human-readable text, supporting detailed output with matched text, capture groups, and summary statistics.
    export function formatRefactorResults(
      results: RefactorResult[],
      options?: RefactorFormatOptions | boolean
    ): string {
      // Handle backward compatibility - if boolean is passed, treat as dryRun
      const formatOptions: RefactorFormatOptions =
        typeof options === 'boolean' ? { dryRun: options } : options || {};
      if (results.length === 0) {
        return 'No matches found for the given pattern';
      }
    
      if (formatOptions.includeCaptureGroups || formatOptions.includeMatchedText) {
        return formatDetailedRefactorResults(results, formatOptions);
      }
    
      const formattedResults = results.map(
        result =>
          `${result.filePath}: ${result.replacements} replacements${formatOptions.dryRun ? ' (dry run)' : ''}`
      );
    
      const totalReplacements = results.reduce(
        (sum, result) => sum + result.replacements,
        0
      );
    
      return `Refactoring completed:\n${formattedResults.join('\n')}\n\nTotal: ${totalReplacements} replacements in ${results.length} files`;
    }
    
    function formatDetailedRefactorResults(
      results: RefactorResult[],
      options: RefactorFormatOptions
    ): string {
      const output: string[] = [
        `Refactoring completed${options.dryRun ? ' (dry run)' : ''}:`,
      ];
    
      for (const result of results) {
        output.push(`\n${result.filePath}: ${result.replacements} replacements`);
    
        for (const match of result.matches) {
          if (options.includeMatchedText) {
            output.push(
              `  Line ${match.line}: ${match.original} → ${match.replaced}`
            );
          } else {
            output.push(`  Line ${match.line}: ${match.content}`);
          }
    
          if (
            options.includeCaptureGroups &&
            match.captureGroups &&
            match.captureGroups.length > 0
          ) {
            output.push(`    └─ Captured: [${match.captureGroups.join(', ')}]`);
          }
        }
      }
    
      const totalReplacements = results.reduce(
        (sum, result) => sum + result.replacements,
        0
      );
      output.push(
        `\nTotal: ${totalReplacements} replacements in ${results.length} files${options.dryRun ? ' (dry run)' : ''}`
      );
    
      return output.join('\n');
    }
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 mentions 'refactor code' which implies mutation/write operations, but doesn't specify whether this modifies files in-place, creates backups, requires confirmation, or has any safety mechanisms. It also doesn't describe error handling, performance implications, or what the tool returns. The description is too vague about the actual behavior beyond the basic operation.

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 extremely concise at just one sentence that directly states the core functionality. Every word earns its place: 'Refactor code' establishes the action, 'by replacing search pattern with replace pattern' explains the mechanism, and 'using regex' specifies the technology. There's no wasted verbiage or unnecessary elaboration.

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 this is a mutation tool with 6 parameters, no annotations, and no output schema, the description is insufficiently complete. It doesn't explain what happens after refactoring (e.g., preview vs. apply, success/failure reporting), doesn't mention the optional parameters' purposes, and provides no safety warnings for a tool that modifies code. For a complex refactoring operation, more context is needed.

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?

Schema description coverage is 100%, so all parameters are documented in the schema. The description adds minimal value beyond the schema by mentioning 'regex' and 'search pattern with replace pattern', which aligns with the schema's 'search_pattern' and 'replace_pattern' parameters. However, it doesn't explain the relationship between parameters or provide usage examples that would help understand how they work together.

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 verb 'refactor' and the resource 'code', specifying it uses regex patterns for search and replace. It distinguishes from the sibling 'code_search' by indicating this is a modification operation rather than just searching. However, it doesn't specify what kind of refactoring (e.g., renaming, restructuring) or the scope beyond regex replacement.

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. It doesn't mention the sibling 'code_search' tool, nor does it specify scenarios where regex-based refactoring is appropriate versus other refactoring methods. There's no information about prerequisites, limitations, or when not to use it.

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

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/myuon/refactor-mcp'

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