diff --git a/README.md b/README.md
index 9077757..32afdca 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ A Go-based MCP (Model Context Protocol) server for Claude Code providing intelli
- **AST-Aware File Reading**: Read files with symbol extraction using Tree-sitter
- **Code Pattern Matching**: Query code using patterns with capture placeholders
- **LSP Integration**: Go-to-definition, find references, and symbol info via language servers
-- **Safe Editing**: AST-aware file editing with syntax validation and preview
+- **Safe Editing**: AST-aware file editing with syntax validation (edit_apply)
- **Multi-Language Support**: Go, TypeScript, JavaScript, Python, C, C++, HTML, Vue, React
- **Token Efficient**: Optimized for minimal token usage with symbols-only mode and output limiting
@@ -140,13 +140,13 @@ For optimal performance, keep the most frequently used tools loaded at startup a
"filepuff": {
"command": "mcp-filepuff",
"args": ["-workspace", "."],
- "alwaysAllow": ["file_read", "file_search", "edit_apply", "edit_preview"]
+ "alwaysAllow": ["file_read", "file_search", "edit_apply"]
}
}
}
```
-This keeps `file_read`, `file_search`, `edit_apply`, and `edit_preview` immediately available while deferring less frequently used tools (`ping`, `ast_query`, `symbol_at`, `find_definition`, `find_references`).
+This keeps `file_read`, `file_search`, and `edit_apply` immediately available while deferring less frequently used tools (`ping`, `ast_query`, `symbol_at`, `find_definition`, `find_references`).
#### System Prompt Guidance
@@ -158,7 +158,7 @@ You have access to filepuff MCP tools providing:
- Fast regex search powered by ripgrep (file_search)
- Structural code pattern matching across 9+ languages (ast_query)
- LSP-powered go-to-definition, find-references, and symbol info (find_definition, find_references, symbol_at)
-- AST-aware file editing with syntax validation and preview (edit_preview, edit_apply)
+- AST-aware file editing with syntax validation (edit_apply)
```
## Usage
@@ -241,7 +241,7 @@ When performing file operations, prefer filepuff MCP tools over built-in equival
| Read files | `mcp__filepuff__file_read` | Read |
| Search content | `mcp__filepuff__file_search` | Grep |
| AST pattern search | `mcp__filepuff__ast_query` | Grep/Glob |
-| Edit files | `mcp__filepuff__edit_preview` + `mcp__filepuff__edit_apply` | Edit |
+| Edit files | `mcp__filepuff__edit_apply` | Edit |
| Find definitions | `mcp__filepuff__find_definition` | Grep |
| Find references | `mcp__filepuff__find_references` | Grep |
| Symbol info | `mcp__filepuff__symbol_at` | - |
@@ -399,8 +399,8 @@ Find all references to the symbol at a specific position.
---
-### `edit_preview`
-Preview an edit without applying it. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++), and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).
+### `edit_apply`
+Apply an edit to a file. Uses AST-aware editing for code files with syntax validation, and text-based editing for other files.
**Parameters**:
- `file` (required): Path to the file to edit
@@ -420,13 +420,6 @@ Preview an edit without applying it. Uses AST-aware editing for code files (Go,
- `selector_text`: Exact text to match (must be unique or use selector_index)
- `selector_pattern`: Regex pattern to match
----
-
-### `edit_apply`
-Apply an edit to a file. Uses AST-aware editing for code files with syntax validation, and text-based editing for other files.
-
-**Parameters**: Same as `edit_preview`
-
**Example (AST mode - Go file)**:
```json
{
@@ -544,8 +537,7 @@ make clean
│ MCP Server │
├─────────────────────────────────────────────────────────┤
│ Tools: file_search, file_read, ast_query, symbol_at, │
-│ find_definition, find_references, │
-│ edit_preview, edit_apply, ping │
+│ find_definition, find_references, edit_apply, ping │
├─────────────────────────────────────────────────────────┤
│ Core Engines │
├───────────┬─────────────┬────────────┬─────────────────┤
@@ -746,7 +738,7 @@ flowchart TB
C -->|Read| E[file_read]
C -->|Query| F[ast_query]
C -->|LSP| G[symbol_at
find_definition
find_references]
- C -->|Edit| H[edit_preview
edit_apply]
+ C -->|Edit| H[edit_apply]
end
subgraph "Core Engines"
@@ -819,7 +811,6 @@ The edit engine validates syntax before and after edits.
**Solution**:
- Ensure `new_content` is syntactically valid for the target language
-- Use `edit_preview` first to see the proposed changes
- Check that the selector matches exactly one node
#### Timeout Errors
diff --git a/cmd/docgen/main.go b/cmd/docgen/main.go
index c2aa9fe..da5e71e 100644
--- a/cmd/docgen/main.go
+++ b/cmd/docgen/main.go
@@ -175,34 +175,6 @@ func AllTools() []Tool {
"Results grouped by file",
},
},
- {
- Name: "edit_preview",
- Description: "Preview an edit without applying it. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++), and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).",
- Category: "Edit Operations",
- ReadOnly: true,
- Parameters: []ToolParameter{
- {Name: "file", Type: "string", Required: true, Description: "Path to the file to edit"},
- {Name: "operation", Type: "string", Required: true, Description: "Edit operation: replace, insert_before, insert_after, delete"},
- {Name: "new_content", Type: "string", Required: false, Description: "New content (required for replace/insert operations)"},
- {Name: "selector_kind", Type: "string", Required: false, Description: "AST node type to match (e.g., function_declaration, class_declaration). For code files only."},
- {Name: "selector_name", Type: "string", Required: false, Description: "Name of the symbol to match. For code files only."},
- {Name: "selector_line", Type: "number", Required: false, Description: "Line number (1-indexed). For AST mode: narrows search. For text mode: start of line range."},
- {Name: "selector_index", Type: "number", Required: false, Description: "Index of the match to use if multiple matches found (default: 0)"},
- {Name: "selector_line_end", Type: "number", Required: false, Description: "End line number for range selection (text mode). Used with selector_line."},
- {Name: "selector_text", Type: "string", Required: false, Description: "Exact text to match (text mode). Must be unique or use selector_index."},
- {Name: "selector_pattern", Type: "string", Required: false, Description: "Regex pattern to match (text mode). Must be unique or use selector_index."},
- },
- Examples: []string{
- `{"file": "server.go", "operation": "replace", "selector_kind": "function_declaration", "selector_name": "Hello", "new_content": "func Hello() {\\n\\tprintln(\\"New Hello\\")\\n}"}`,
- `{"file": "README.md", "operation": "replace", "selector_text": "## Installation", "new_content": "## Getting Started"}`,
- `{"file": "package.json", "operation": "replace", "selector_pattern": "\\"version\\":\\\\s*\\"[^\\"]+\\"", "new_content": "\\"version\\": \\"2.0.0\\""}`,
- },
- Notes: []string{
- "Returns a diff showing proposed changes",
- "Does not modify the file",
- "Use to validate changes before applying",
- },
- },
{
Name: "edit_apply",
Description: "Apply an edit to a file. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++) with syntax validation, and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).",
diff --git a/docs/API.md b/docs/API.md
index 0348bad..38561fb 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -1,6 +1,6 @@
# MCP Filepuff API Reference
-> Auto-generated on 2026-01-28
+> Auto-generated on 2026-03-12
This document provides detailed API documentation for all MCP tools available in filepuff.
@@ -24,7 +24,6 @@ This document provides detailed API documentation for all MCP tools available in
- [`find_references`](#find_references)
### Edit Operations
-- [`edit_preview`](#edit_preview)
- [`edit_apply`](#edit_apply)
---
@@ -47,10 +46,9 @@ Health check - returns pong to verify the server is running
{"tool": "ping"}
```
-**Returns:** `"pong"` text string.
-
**Notes:**
+- Returns: "pong"
- Use to verify server connectivity
---
@@ -85,8 +83,6 @@ Search for text patterns in files using ripgrep. Supports regex patterns, file t
{"pattern": "TODO", "ignore_case": true, "context_lines": 3}
```
-**Returns:** Results grouped by file with match context. Format: `"Found N matches in M files:"` followed by file sections, each with matching lines prefixed by `"L{line}│"` and context lines prefixed by `" │"`.
-
**Notes:**
- Requires ripgrep (rg) to be installed
@@ -131,8 +127,6 @@ Read a file's contents with optional line range and AST symbol summary
{"path": "large_file.go", "max_lines": 100}
```
-**Returns:** File content with numbered lines (format: `" 12│ line text"`). When `include_ast=true`: prepends symbol summary (`"**file.go** (N lines, go)\nSymbols:\n func Name L12\n struct Config L45"`). When `symbols_only=true`: returns only the symbol summary (~95% fewer tokens). When `max_lines` is set: truncates output with `"[... N more lines omitted]"` notice.
-
**Notes:**
- symbols_only mode reduces token usage by ~90-98%
@@ -175,8 +169,6 @@ Search for AST patterns in code files. Use code patterns with $VAR placeholders
{"pattern": "function $NAME($PROPS) { $$$BODY }", "language": "javascript", "name_matches": "^[A-Z]"}
```
-**Returns:** `"Found N match(es):"` followed by entries in format `"**file:line** (node_type)"` with code blocks and captured variables (`$NAME=value`). Returns `"No matches found."` when no results.
-
**Notes:**
- $NAME captures identifiers
@@ -208,8 +200,6 @@ Get information about the symbol at a specific position in a file. Returns type,
{"file": "server.go", "line": 25, "column": 10}
```
-**Returns:** `"**Symbol Information**"` followed by hover/type information from LSP, or `"**Symbol Information** (AST fallback)"` with node type and text when LSP unavailable. Returns `"No symbol information available at this position."` when nothing is found.
-
**Notes:**
- Requires LSP server for full type information
@@ -237,11 +227,10 @@ Find the definition of the symbol at a specific position. Uses LSP to locate whe
{"file": "server.go", "line": 42, "column": 15}
```
-**Returns:** `"Found N definition(s):"` with entries showing `"**file:line:column**"` and a 3-line code preview with the target line marked by `">"`. Returns `"No definition found."` when the symbol has no definition.
-
**Notes:**
- Requires language server for the file type
+- Returns file path, line, and column of definition
- Shows code preview at definition location
---
@@ -271,8 +260,6 @@ Find all references to the symbol at a specific position. Uses LSP to locate all
{"file": "server.go", "line": 42, "column": 15, "include_declaration": false}
```
-**Returns:** `"Found N reference(s):"` grouped by file, each showing `"**file** (count)"` with locations as `"L{line}:{column}"`. Returns `"No references found."` when no usages exist.
-
**Notes:**
- Requires language server for the file type
@@ -282,49 +269,6 @@ Find all references to the symbol at a specific position. Uses LSP to locate all
### Edit Operations
-#### `edit_preview`
-
-Preview an edit without applying it. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++), and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).
-
-🔒 **Read-only**: This tool does not modify files.
-
-**Parameters:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `file` | `string` | **Yes** | Path to the file to edit |
-| `operation` | `string` | **Yes** | Edit operation: replace, insert_before, insert_after, delete |
-| `new_content` | `string` | No | New content (required for replace/insert operations) |
-| `selector_kind` | `string` | No | AST node type to match (e.g., function_declaration, class_declaration). For code files only. |
-| `selector_name` | `string` | No | Name of the symbol to match. For code files only. |
-| `selector_line` | `number` | No | Line number (1-indexed). For AST mode: narrows search. For text mode: start of line range. |
-| `selector_index` | `number` | No | Index of the match to use if multiple matches found (default: 0) |
-| `selector_line_end` | `number` | No | End line number for range selection (text mode). Used with selector_line. |
-| `selector_text` | `string` | No | Exact text to match (text mode). Must be unique or use selector_index. |
-| `selector_pattern` | `string` | No | Regex pattern to match (text mode). Must be unique or use selector_index. |
-
-**Examples:**
-
-```json
-{"file": "server.go", "operation": "replace", "selector_kind": "function_declaration", "selector_name": "Hello", "new_content": "func Hello() {\\n\\tprintln(\\"New Hello\\")\\n}"}
-```
-
-```json
-{"file": "README.md", "operation": "replace", "selector_text": "## Installation", "new_content": "## Getting Started"}
-```
-
-```json
-{"file": "package.json", "operation": "replace", "selector_pattern": "\\"version\\":\\\\s*\\"[^\\"]+\\"", "new_content": "\\"version\\": \\"2.0.0\\""}
-```
-
-**Returns:** `"**Edit Preview**"` followed by a unified diff showing proposed changes. Does not modify the file. For code files: uses AST-aware mode with syntax validation. For other files: uses text-based mode.
-
-**Notes:**
-
-- Use to validate changes before applying
-
----
-
#### `edit_apply`
Apply an edit to a file. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++) with syntax validation, and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).
@@ -356,10 +300,9 @@ Apply an edit to a file. Uses AST-aware editing for code files (Go, TypeScript,
{"file": "config.yaml", "operation": "replace", "selector_line": 5, "selector_line_end": 10, "new_content": "database:\\n host: production.db.example.com\\n port: 5432"}
```
-**Returns:** `"**Edit Applied Successfully**"` followed by a unified diff of the changes made. For code files, validates syntax before writing — returns an error if the edit would produce invalid syntax.
-
**Notes:**
+- For code files: validates syntax before and after edit
- Preserves file permissions
- Uses atomic writes for safety
- File locking prevents concurrent edits
diff --git a/docs/ERROR_CODES.md b/docs/ERROR_CODES.md
index 4b54383..0a3d493 100644
--- a/docs/ERROR_CODES.md
+++ b/docs/ERROR_CODES.md
@@ -451,8 +451,7 @@ Review the edit request and ensure all required fields are provided.
**Remediation**:
1. Validate `new_content` syntax independently
-2. Use `edit_preview` to see the proposed changes
-3. Ensure the edit maintains valid syntax
+2. Ensure the edit maintains valid syntax
---
@@ -622,9 +621,8 @@ mcp-filepuff -workspace /path/to/workspace
**Symptoms**: Edit operation rejected with syntax error
**Solution**:
-1. Use `edit_preview` first to see proposed changes
-2. Validate `new_content` is syntactically correct
-3. Check that surrounding code structure is maintained
+1. Validate `new_content` is syntactically correct
+2. Check that surrounding code structure is maintained
### Scenario 3: Search Returns Too Many Results
diff --git a/internal/server/handlers_edit.go b/internal/server/handlers_edit.go
index 3e1fe19..c14e241 100644
--- a/internal/server/handlers_edit.go
+++ b/internal/server/handlers_edit.go
@@ -22,18 +22,13 @@ func unescapeNewlines(s string) string {
return s
}
-// handleEditPreview handles the edit_preview tool.
-func (s *Server) handleEditPreview(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- return s.handleEdit(ctx, request, false)
-}
-
// handleEditApply handles the edit_apply tool.
func (s *Server) handleEditApply(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- return s.handleEdit(ctx, request, true)
+ return s.handleEdit(ctx, request)
}
-// handleEdit is the shared implementation for edit_preview and edit_apply.
-func (s *Server) handleEdit(ctx context.Context, request mcp.CallToolRequest, apply bool) (*mcp.CallToolResult, error) {
+// handleEdit performs an edit operation (always applies changes).
+func (s *Server) handleEdit(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
file, err := request.RequireString("file")
if err != nil {
return mcp.NewToolResultError("file is required"), nil
@@ -85,13 +80,8 @@ func (s *Server) handleEdit(ctx context.Context, request mcp.CallToolRequest, ap
},
}
- // Perform edit
- var result *edit.EditResult
- if apply {
- result, err = s.editor.Apply(ctx, astEdit)
- } else {
- result, err = s.editor.Preview(ctx, astEdit)
- }
+ // Perform edit (always apply)
+ result, err := s.editor.Apply(ctx, astEdit)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("edit failed: %s", errors.SanitizeError(err))), nil
@@ -103,11 +93,7 @@ func (s *Server) handleEdit(ctx context.Context, request mcp.CallToolRequest, ap
// Format output
var output strings.Builder
- if apply {
- output.WriteString("**Edit Applied Successfully**\n\n")
- } else {
- output.WriteString("**Edit Preview**\n\n")
- }
+ output.WriteString("**Edit Applied Successfully**\n\n")
output.WriteString("Diff:\n```diff\n")
output.WriteString(result.Diff)
diff --git a/internal/server/integration_test.go b/internal/server/integration_test.go
index 87be036..9ca7156 100644
--- a/internal/server/integration_test.go
+++ b/internal/server/integration_test.go
@@ -96,35 +96,17 @@ func Hello() string {
}
})
- // Test 4: Edit preview and apply
+ // Test 4: Edit workflow
t.Run("edit_workflow", func(t *testing.T) {
- // Preview edit
- previewReq := mcp.CallToolRequest{}
- previewReq.Params.Arguments = map[string]interface{}{
+ // Apply edit directly (preview removed to avoid confusing LLMs)
+ applyReq := mcp.CallToolRequest{}
+ applyReq.Params.Arguments = map[string]interface{}{
"file": testFile,
"operation": "replace",
"selector_kind": "function_declaration",
"selector_name": "Hello",
"new_content": "func Hello() string {\n\treturn \"goodbye\"\n}",
}
- previewResult, err := srv.handleEditPreview(ctx, previewReq)
- if err != nil {
- t.Errorf("handleEditPreview() error = %v", err)
- }
- if previewResult == nil {
- t.Fatal("handleEditPreview() returned nil")
- return
- }
-
- // Verify file unchanged after preview
- originalContent, _ := os.ReadFile(testFile)
- if string(originalContent) != content {
- t.Error("preview should not modify file")
- }
-
- // Apply edit
- applyReq := mcp.CallToolRequest{}
- applyReq.Params.Arguments = previewReq.Params.Arguments
applyResult, err := srv.handleEditApply(ctx, applyReq)
if err != nil {
t.Errorf("handleEditApply() error = %v", err)
@@ -267,10 +249,8 @@ func TestMCPErrorResponses(t *testing.T) {
expectError: true,
},
{
- name: "edit_missing_file",
- handler: func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- return srv.handleEdit(ctx, req, false)
- },
+ name: "edit_missing_file",
+ handler: srv.handleEditApply,
setupReq: func() mcp.CallToolRequest {
req := mcp.CallToolRequest{}
req.Params.Arguments = map[string]interface{}{
@@ -281,10 +261,8 @@ func TestMCPErrorResponses(t *testing.T) {
expectError: true,
},
{
- name: "edit_missing_operation",
- handler: func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- return srv.handleEdit(ctx, req, false)
- },
+ name: "edit_missing_operation",
+ handler: srv.handleEditApply,
setupReq: func() mcp.CallToolRequest {
req := mcp.CallToolRequest{}
req.Params.Arguments = map[string]interface{}{
@@ -376,7 +354,7 @@ func Add(a, b int) int {
return
}
- // 3. Preview edit
+ // 3. Edit (no preview)
editReq := mcp.CallToolRequest{}
editReq.Params.Arguments = map[string]interface{}{
"file": testFile,
@@ -385,12 +363,12 @@ func Add(a, b int) int {
"selector_name": "Add",
"new_content": "func Add(a, b int) int {\n\treturn a + b + 1\n}",
}
- editResult, err := srv.handleEditPreview(ctx, editReq)
+ editResult, err := srv.handleEditApply(ctx, editReq)
if err != nil {
- t.Fatalf("handleEditPreview() error = %v", err)
+ t.Fatalf("handleEditApply() error = %v", err)
}
if editResult == nil {
- t.Fatal("handleEditPreview() returned nil")
+ t.Fatal("handleEditApply() returned nil")
return
}
})
diff --git a/internal/server/server.go b/internal/server/server.go
index 82ff009..80c038c 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -290,54 +290,6 @@ func (s *Server) registerTools() {
}
// Register edit tools
- s.mcp.AddTool(
- mcp.NewTool("edit_preview",
- mcp.WithDescription("Preview an edit without applying it. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++, Rust), and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).\n\n"+
- "Returns: \"**Edit Preview**\" followed by a unified diff showing proposed changes. Does not modify the file. "+
- "For code files: uses AST-aware mode with syntax validation. For other files: uses text-based mode.\n\n"+
- "Examples:\n"+
- " AST mode: {\"file\": \"main.go\", \"operation\": \"replace\", \"selector_kind\": \"function_declaration\", \"selector_name\": \"Hello\", \"new_content\": \"func Hello() {\\n\\treturn\\n}\"}\n"+
- " Text mode: {\"file\": \"README.md\", \"operation\": \"replace\", \"selector_text\": \"## Old Header\", \"new_content\": \"## New Header\"}\n"+
- " Line range: {\"file\": \"config.yaml\", \"operation\": \"replace\", \"selector_line\": 5, \"selector_line_end\": 10, \"new_content\": \"key: value\"}"),
- mcp.WithString("file",
- mcp.Required(),
- mcp.Description("Path to the file to edit"),
- ),
- mcp.WithString("operation",
- mcp.Required(),
- mcp.Description("Edit operation: replace, insert_before, insert_after, delete"),
- ),
- mcp.WithString("new_content",
- mcp.Description("New content (required for replace/insert operations)"),
- ),
- // AST-mode selectors (for code files)
- mcp.WithString("selector_kind",
- mcp.Description("AST node type to match (e.g., function_declaration, class_declaration). For code files only."),
- ),
- mcp.WithString("selector_name",
- mcp.Description("Name of the symbol to match. For code files only."),
- ),
- // Shared selectors
- mcp.WithNumber("selector_line",
- mcp.Description("Line number (1-indexed). For AST mode: narrows search. For text mode: start of line range."),
- ),
- mcp.WithNumber("selector_index",
- mcp.Description("Index of the match to use if multiple matches found (default: 0)"),
- ),
- // Text-mode selectors (for non-code files or explicit text matching)
- mcp.WithNumber("selector_line_end",
- mcp.Description("End line number for range selection (text mode). Used with selector_line."),
- ),
- mcp.WithString("selector_text",
- mcp.Description("Exact text to match (text mode). Must be unique or use selector_index."),
- ),
- mcp.WithString("selector_pattern",
- mcp.Description("Regex pattern to match (text mode). Must be unique or use selector_index."),
- ),
- ),
- s.handleEditPreview,
- )
-
s.mcp.AddTool(
mcp.NewTool("edit_apply",
mcp.WithDescription("Apply an edit to a file. Uses AST-aware editing for code files (Go, TypeScript, JavaScript, Python, C, C++, Rust) with syntax validation, and text-based editing for other files (Markdown, JSON, YAML, config files, etc.).\n\n"+
diff --git a/internal/server/server_test.go b/internal/server/server_test.go
index 2df72af..caea7f4 100644
--- a/internal/server/server_test.go
+++ b/internal/server/server_test.go
@@ -283,56 +283,6 @@ func Goodbye() error {
}
}
-func TestHandleEditPreview(t *testing.T) {
- tmpDir := t.TempDir()
-
- // Create a test file
- testFile := filepath.Join(tmpDir, "test.go")
- content := `package main
-
-func Hello() {
- println("Hello")
-}
-`
- if err := os.WriteFile(testFile, []byte(content), 0600); err != nil {
- t.Fatalf("failed to write test file: %v", err)
- }
-
- cfg := &config.Config{WorkspaceRoot: tmpDir, EnableLSP: false}
- logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
-
- srv, err := New(cfg, logger)
- if err != nil {
- t.Fatalf("New() error = %v", err)
- }
-
- ctx := context.Background()
- req := mcp.CallToolRequest{}
- req.Params.Arguments = map[string]interface{}{
- "file": testFile,
- "operation": "replace",
- "selector_kind": "function_declaration",
- "selector_name": "Hello",
- "new_content": "func Hello() {\n\tprintln(\"Goodbye\")\n}",
- }
-
- result, err := srv.handleEdit(ctx, req, false)
- if err != nil {
- t.Errorf("handleEdit(preview) error = %v", err)
- }
-
- if result == nil {
- t.Fatal("handleEdit(preview) returned nil result")
- return
- }
-
- // Verify file was NOT modified (it's just a preview)
- fileContent, _ := os.ReadFile(testFile)
- if string(fileContent) != content {
- t.Error("handleEdit(preview) should not modify the file")
- }
-}
-
func TestHandleEditApply(t *testing.T) {
tmpDir := t.TempDir()
@@ -366,20 +316,20 @@ func Hello() {
"new_content": "func Hello() {\n\tprintln(\"Goodbye\")\n}",
}
- result, err := srv.handleEdit(ctx, req, true)
+ result, err := srv.handleEditApply(ctx, req)
if err != nil {
- t.Errorf("handleEdit(apply) error = %v", err)
+ t.Errorf("handleEditApply error = %v", err)
}
if result == nil {
- t.Fatal("handleEdit(apply) returned nil result")
+ t.Fatal("handleEditApply returned nil result")
return
}
// Verify file WAS modified
fileContent, _ := os.ReadFile(testFile)
if string(fileContent) == content {
- t.Error("handleEdit(apply) should modify the file")
+ t.Error("handleEditApply should modify the file")
}
}