Skip to content

Commit 3e2e4c1

Browse files
authored
Implement delete file (mark3labs#21)
1 parent 3f8a156 commit 3e2e4c1

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ This MCP server provides secure access to the local filesystem via the Model Con
2828
- Move or rename files and directories
2929
- Parameters: `source` (required): Source path of the file or directory, `destination` (required): Destination path
3030

31+
- **delete_file**
32+
- Delete a file or directory from the file system
33+
- Parameters: `path` (required): Path to the file or directory to delete, `recursive` (optional): Whether to recursively delete directories (default: false)
34+
3135
#### Directory Operations
3236

3337
- **list_directory**

filesystemserver/handler.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,138 @@ func (fs *FilesystemHandler) handleReadMultipleFiles(
19371937
}, nil
19381938
}
19391939

1940+
func (fs *FilesystemHandler) handleDeleteFile(
1941+
ctx context.Context,
1942+
request mcp.CallToolRequest,
1943+
) (*mcp.CallToolResult, error) {
1944+
path, ok := request.Params.Arguments["path"].(string)
1945+
if !ok {
1946+
return nil, fmt.Errorf("path must be a string")
1947+
}
1948+
1949+
// Handle empty or relative paths like "." or "./" by converting to absolute path
1950+
if path == "." || path == "./" {
1951+
// Get current working directory
1952+
cwd, err := os.Getwd()
1953+
if err != nil {
1954+
return &mcp.CallToolResult{
1955+
Content: []mcp.Content{
1956+
mcp.TextContent{
1957+
Type: "text",
1958+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
1959+
},
1960+
},
1961+
IsError: true,
1962+
}, nil
1963+
}
1964+
path = cwd
1965+
}
1966+
1967+
validPath, err := fs.validatePath(path)
1968+
if err != nil {
1969+
return &mcp.CallToolResult{
1970+
Content: []mcp.Content{
1971+
mcp.TextContent{
1972+
Type: "text",
1973+
Text: fmt.Sprintf("Error: %v", err),
1974+
},
1975+
},
1976+
IsError: true,
1977+
}, nil
1978+
}
1979+
1980+
// Check if path exists
1981+
info, err := os.Stat(validPath)
1982+
if os.IsNotExist(err) {
1983+
return &mcp.CallToolResult{
1984+
Content: []mcp.Content{
1985+
mcp.TextContent{
1986+
Type: "text",
1987+
Text: fmt.Sprintf("Error: Path does not exist: %s", path),
1988+
},
1989+
},
1990+
IsError: true,
1991+
}, nil
1992+
} else if err != nil {
1993+
return &mcp.CallToolResult{
1994+
Content: []mcp.Content{
1995+
mcp.TextContent{
1996+
Type: "text",
1997+
Text: fmt.Sprintf("Error accessing path: %v", err),
1998+
},
1999+
},
2000+
IsError: true,
2001+
}, nil
2002+
}
2003+
2004+
// Extract recursive parameter (optional, default: false)
2005+
recursive := false
2006+
if recursiveParam, ok := request.Params.Arguments["recursive"]; ok {
2007+
if r, ok := recursiveParam.(bool); ok {
2008+
recursive = r
2009+
}
2010+
}
2011+
2012+
// Check if it's a directory and handle accordingly
2013+
if info.IsDir() {
2014+
if !recursive {
2015+
return &mcp.CallToolResult{
2016+
Content: []mcp.Content{
2017+
mcp.TextContent{
2018+
Type: "text",
2019+
Text: fmt.Sprintf("Error: %s is a directory. Use recursive=true to delete directories.", path),
2020+
},
2021+
},
2022+
IsError: true,
2023+
}, nil
2024+
}
2025+
2026+
// It's a directory and recursive is true, so remove it
2027+
if err := os.RemoveAll(validPath); err != nil {
2028+
return &mcp.CallToolResult{
2029+
Content: []mcp.Content{
2030+
mcp.TextContent{
2031+
Type: "text",
2032+
Text: fmt.Sprintf("Error deleting directory: %v", err),
2033+
},
2034+
},
2035+
IsError: true,
2036+
}, nil
2037+
}
2038+
2039+
return &mcp.CallToolResult{
2040+
Content: []mcp.Content{
2041+
mcp.TextContent{
2042+
Type: "text",
2043+
Text: fmt.Sprintf("Successfully deleted directory %s", path),
2044+
},
2045+
},
2046+
}, nil
2047+
}
2048+
2049+
// It's a file, delete it
2050+
if err := os.Remove(validPath); err != nil {
2051+
return &mcp.CallToolResult{
2052+
Content: []mcp.Content{
2053+
mcp.TextContent{
2054+
Type: "text",
2055+
Text: fmt.Sprintf("Error deleting file: %v", err),
2056+
},
2057+
},
2058+
IsError: true,
2059+
}, nil
2060+
}
2061+
2062+
return &mcp.CallToolResult{
2063+
Content: []mcp.Content{
2064+
mcp.TextContent{
2065+
Type: "text",
2066+
Text: fmt.Sprintf("Successfully deleted file %s", path),
2067+
},
2068+
},
2069+
}, nil
2070+
}
2071+
19402072
func (fs *FilesystemHandler) handleListAllowedDirectories(
19412073
ctx context.Context,
19422074
request mcp.CallToolRequest,

filesystemserver/server.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,17 @@ func NewFilesystemServer(allowedDirs []string) (*server.MCPServer, error) {
145145
),
146146
), h.handleTree)
147147

148+
s.AddTool(mcp.NewTool(
149+
"delete_file",
150+
mcp.WithDescription("Delete a file or directory from the file system."),
151+
mcp.WithString("path",
152+
mcp.Description("Path to the file or directory to delete"),
153+
mcp.Required(),
154+
),
155+
mcp.WithBoolean("recursive",
156+
mcp.Description("Whether to recursively delete directories (default: false)"),
157+
),
158+
), h.handleDeleteFile)
159+
148160
return s, nil
149161
}

0 commit comments

Comments
 (0)