Skip to main content
Glama

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'); }

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