package handler
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/mark3labs/mcp-go/mcp"
)
func (fs *FilesystemHandler) HandleMoveFile(
ctx context.Context,
request mcp.CallToolRequest,
) (*mcp.CallToolResult, error) {
source, err := request.RequireString("source")
if err != nil {
return nil, err
}
destination, err := request.RequireString("destination")
if err != nil {
return nil, err
}
// Handle empty or relative paths for source
if source == "." || source == "./" {
// Get current working directory
cwd, err := os.Getwd()
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error resolving current directory: %v", err),
},
},
IsError: true,
}, nil
}
source = cwd
}
// Handle empty or relative paths for destination
if destination == "." || destination == "./" {
// Get current working directory
cwd, err := os.Getwd()
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error resolving current directory: %v", err),
},
},
IsError: true,
}, nil
}
destination = cwd
}
validSource, err := fs.validatePath(source)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error with source path: %v", err),
},
},
IsError: true,
}, nil
}
// Check if source exists
if _, err := os.Stat(validSource); os.IsNotExist(err) {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error: Source does not exist: %s", source),
},
},
IsError: true,
}, nil
}
// For destination path, validate the parent directory first and create it if needed
destDir := filepath.Dir(destination)
validDestDir, err := fs.validatePath(destDir)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error with destination directory path: %v", err),
},
},
IsError: true,
}, nil
}
// Create parent directory for destination if it doesn't exist
if err := os.MkdirAll(validDestDir, 0755); err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error creating destination directory: %v", err),
},
},
IsError: true,
}, nil
}
// Now validate the full destination path
validDest, err := fs.validatePath(destination)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error with destination path: %v", err),
},
},
IsError: true,
}, nil
}
if err := os.Rename(validSource, validDest); err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error moving file: %v", err),
},
},
IsError: true,
}, nil
}
resourceURI := pathToResourceURI(validDest)
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf(
"Successfully moved %s to %s",
source,
destination,
),
},
mcp.EmbeddedResource{
Type: "resource",
Resource: mcp.TextResourceContents{
URI: resourceURI,
MIMEType: "text/plain",
Text: fmt.Sprintf("Moved file: %s", validDest),
},
},
},
}, nil
}