Commit 2c1bba8

mo khan <mo@mokhan.ca>
2025-06-22 20:09:00
feat: add edit-file prompt to filesystem server
- Add registerPrompts method to filesystem server - Implement HandleEditFilePrompt for interactive file editing guidance - Support required path and instructions arguments, optional context - Generate step-by-step workflow for file editing operations - Include path validation and security checks within allowed directories Features: - path (required): File path to edit (validated against allowed directories) - instructions (required): Clear description of changes to make - context (optional): Additional context about why changes are needed Prompt provides: - Step-by-step editing workflow guidance - File reading โ†’ analysis โ†’ editing โ†’ verification approach - Context-aware descriptions and error handling - Security validation preventing access outside allowed directories Testing shows: - Proper prompt registration and argument handling - Dynamic descriptions based on filename and context - Comprehensive error handling for missing/invalid arguments - Security enforcement of directory restrictions - Clear user/assistant conversation flow for editing guidance ๐Ÿค– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2241040
Changed files (1)
pkg
filesystem
pkg/filesystem/server.go
@@ -36,8 +36,9 @@ func New(allowedDirs []string) *Server {
 		allowedDirectories: normalizedDirs,
 	}
 
-	// Register all filesystem tools
+	// Register all filesystem tools and prompts
 	fsServer.registerTools()
+	fsServer.registerPrompts()
 
 	return fsServer
 }
@@ -58,6 +59,33 @@ func (fs *Server) registerTools() {
 	fs.RegisterTool("list_allowed_directories", fs.HandleListAllowedDirectories)
 }
 
+// registerPrompts registers all Filesystem prompts with the server
+func (fs *Server) registerPrompts() {
+	editFilePrompt := mcp.Prompt{
+		Name:        "edit-file",
+		Description: "Prompt for interactive file editing with guidance on changes to make",
+		Arguments: []mcp.PromptArgument{
+			{
+				Name:        "path",
+				Description: "Path to the file to edit",
+				Required:    true,
+			},
+			{
+				Name:        "instructions",
+				Description: "Description of what changes need to be made to the file",
+				Required:    true,
+			},
+			{
+				Name:        "context",
+				Description: "Additional context about why these changes are needed (optional)",
+				Required:    false,
+			},
+		},
+	}
+	
+	fs.RegisterPrompt(editFilePrompt, fs.HandleEditFilePrompt)
+}
+
 // ListTools returns all available Filesystem tools
 func (fs *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
@@ -957,3 +985,78 @@ func (fs *Server) searchFiles(rootPath, pattern string, excludePatterns []string
 
 	return results, err
 }
+
+// Prompt handlers
+
+func (fs *Server) HandleEditFilePrompt(req mcp.GetPromptRequest) (mcp.GetPromptResult, error) {
+	filePath, hasPath := req.Arguments["path"].(string)
+	instructions, hasInstructions := req.Arguments["instructions"].(string)
+	context, hasContext := req.Arguments["context"].(string)
+
+	if !hasPath || filePath == "" {
+		return mcp.GetPromptResult{}, fmt.Errorf("path argument is required")
+	}
+
+	if !hasInstructions || instructions == "" {
+		return mcp.GetPromptResult{}, fmt.Errorf("instructions argument is required")
+	}
+
+	// Validate path (but don't require it to exist yet)
+	_, err := fs.validatePath(filePath)
+	if err != nil {
+		return mcp.GetPromptResult{}, fmt.Errorf("invalid path: %v", err)
+	}
+
+	// Create the prompt messages
+	var messages []mcp.PromptMessage
+
+	// User message with the edit request
+	userContent := fmt.Sprintf(`I need to edit the file at: %s
+
+Instructions for the changes:
+%s`, filePath, instructions)
+
+	if hasContext && context != "" {
+		userContent += fmt.Sprintf("\n\nAdditional context:\n%s", context)
+	}
+
+	userContent += "\n\nPlease help me implement these changes step by step."
+
+	messages = append(messages, mcp.PromptMessage{
+		Role:    "user",
+		Content: mcp.NewTextContent(userContent),
+	})
+
+	// Assistant message with guidance
+	assistantContent := fmt.Sprintf(`I'll help you edit the file %s. Let me break this down:
+
+**Requested changes:**
+%s
+
+**Recommended approach:**
+1. First, I'll read the current file to understand the existing content
+2. Analyze the changes needed based on your instructions
+3. Use the edit_file tool to make the specific modifications
+4. Verify the changes were applied correctly
+
+Let me start by reading the current file:`, filePath, instructions)
+
+	if hasContext && context != "" {
+		assistantContent += fmt.Sprintf("\n\n**Context:** %s", context)
+	}
+
+	messages = append(messages, mcp.PromptMessage{
+		Role:    "assistant",
+		Content: mcp.NewTextContent(assistantContent),
+	})
+
+	description := fmt.Sprintf("File editing guidance for %s", filepath.Base(filePath))
+	if hasContext && context != "" {
+		description += fmt.Sprintf(" (%s)", context)
+	}
+
+	return mcp.GetPromptResult{
+		Description: description,
+		Messages:    messages,
+	}, nil
+}