Add context-aware search/replace with capture groups

This commit is contained in:
Ian Gulliver
2025-06-27 21:38:51 -07:00
parent d16a911a5c
commit b7cbe3a222
2 changed files with 174 additions and 5 deletions

27
main.go
View File

@@ -384,14 +384,14 @@ func main() {
// Define the search_replace tool
searchReplaceTool := mcp.NewTool("search_replace",
mcp.WithDescription("Search and optionally replace text in files using string or regex patterns"),
mcp.WithDescription("Search and optionally replace text in files. Supports context-aware replacements with capture groups."),
mcp.WithString("paths",
mcp.Required(),
mcp.Description("File/directory path or comma-separated paths to search"),
),
mcp.WithString("pattern",
mcp.Required(),
mcp.Description("Search pattern (string or regex)"),
mcp.Description("Search pattern (string or regex). Used for simple search unless context_pattern is provided."),
),
mcp.WithString("replacement",
mcp.Description("Replacement text (omit for search-only)"),
@@ -405,6 +405,12 @@ func main() {
mcp.WithBoolean("include_context",
mcp.Description("Include line context in search results (default: false)"),
),
mcp.WithString("context_pattern",
mcp.Description("Context pattern with capture groups, e.g., '(prefix)(target)(suffix)' to replace only the target"),
),
mcp.WithNumber("target_group",
mcp.Description("Which capture group to replace when using context_pattern (1-based, default: 2 for 3 groups, otherwise last)"),
),
)
mcpServer.AddTool(searchReplaceTool, searchReplaceHandler)
@@ -1032,8 +1038,23 @@ func searchReplaceHandler(ctx context.Context, request mcp.CallToolRequest) (*mc
useRegex := request.GetBool("regex", false)
caseInsensitive := request.GetBool("case_insensitive", false)
includeContext := request.GetBool("include_context", false)
contextPattern := request.GetString("context_pattern", "")
targetGroup := int(request.GetFloat("target_group", 0))
result, err := searchReplace(paths, pattern, replacement, useRegex, caseInsensitive, includeContext)
// If context pattern is provided, use the context-aware replacement
if contextPattern != "" && replacement != nil && targetGroup > 0 {
result, err := searchReplaceWithGroups(paths, contextPattern, *replacement, targetGroup, caseInsensitive)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("search/replace failed: %v", err)), nil
}
jsonData, err := json.Marshal(result)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to marshal result: %v", err)), nil
}
return mcp.NewToolResultText(string(jsonData)), nil
}
result, err := searchReplace(paths, pattern, replacement, useRegex, caseInsensitive, includeContext, contextPattern)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("search/replace failed: %v", err)), nil
}