Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/tools/calculate_directory_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub enum FileSizeOutputFormat {

#[mcp_tool(
name = "calculate_directory_size",
title="Calculate Directory Size",
title="Calculate directory size",
description = concat!("Calculates the total size of a directory specified by `root_path`.",
"It recursively searches for files and sums their sizes. ",
"The result can be returned in either a `human-readable` format or as `bytes`, depending on the specified `output_format` argument.",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/create_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "create_directory",
title="Create Directory",
title="Create directory",
description = concat!("Create a new directory or ensure a directory exists. ",
"Can create multiple nested directories in one operation. ",
"If the directory already exists, this operation will succeed silently. ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/directory_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "directory_tree",
title= "Directory Tree",
title= "Directory tree",
description = concat!("Get a recursive tree view of files and directories as a JSON structure. ",
"Each entry includes 'name', 'type' (file/directory), and 'children' for directories. ",
"Files have no children array, while directories always have a children array (which may be empty). ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/edit_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct EditOperation {

#[mcp_tool(
name = "edit_file",
title="Edit File",
title="Edit file",
description = concat!("Make line-based edits to a text file. ",
"Each edit replaces exact line sequences with new content. ",
"Returns a git-style diff showing the changes made. ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/find_duplicate_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{collections::BTreeMap, fmt::Write};

#[mcp_tool(
name = "find_duplicate_files",
title="Calculate Directory Size",
title="Find duplicate files",
description = concat!("Find duplicate files within a directory and return list of duplicated files as text or json format",
"Optional `pattern` argument can be used to narrow down the file search to specific glob pattern.",
"Optional `exclude_patterns` can be used to exclude certain files matching a glob.",
Expand Down
4 changes: 2 additions & 2 deletions src/tools/find_empty_directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use std::path::Path;

use crate::fs_service::{FileSystemService, utils::OutputFormat};

// head_file
// find_empty_directories
#[mcp_tool(
name = "find_empty_directories",
title="Find Empty Directories",
title="Find empty directories",
description = concat!("Recursively finds all empty directories within the given root path.",
"A directory is considered empty if it contains no files in itself or any of its subdirectories.",
"Operating system metadata files `.DS_Store` (macOS) and `Thumbs.db` (Windows) will be ignored.",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/get_file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "get_file_info",
title="Get File Info",
title="Get file info",
description = concat!("Retrieve detailed metadata about a file or directory. ",
"Returns comprehensive information including size, creation time, ",
"last modified time, permissions, and type. ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/list_allowed_directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "list_allowed_directories",
title="List Allowed Directories",
title="List allowed directories",
description = concat!("Returns a list of directories that the server has permission ",
"to access Subdirectories within these allowed directories are also accessible. ",
"Use this to identify which directories and their nested paths are available ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/list_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "list_directory",
title="List Directory",
title="List directory",
description = concat!("Get a detailed listing of all files and directories in a specified path. ",
"Results clearly distinguish between files and directories with [FILE] and [DIR] ",
"prefixes. This tool is essential for understanding directory structure and ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/list_directory_with_sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::fs_service::utils::format_bytes;

#[mcp_tool(
name = "list_directory_with_sizes",
title="List Directory With File Sizes",
title="List directory with file sizes",
description = concat!("Get a detailed listing of all files and directories in a specified path, including sizes. " ,
"Results clearly distinguish between files and directories with [FILE] and [DIR] prefixes. " ,
"This tool is useful for understanding directory structure and " ,
Expand Down
2 changes: 1 addition & 1 deletion src/tools/move_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "move_file",
title="Move File",
title="Move file",
description = concat!("Move or rename files and directories. Can move files between directories ",
"and rename them in a single operation. If the destination exists, the ",
"operation will fail. Works across different directories and can be used ",
Expand Down
4 changes: 2 additions & 2 deletions src/tools/read_file_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use rust_mcp_sdk::{

use crate::fs_service::FileSystemService;

// head_file
// read_file_lines
#[mcp_tool(
name = "read_file_lines",
title="Read File Lines",
title="Read file lines",
description = concat!("Reads lines from a text file starting at a specified line offset (0-based) and continues for the specified number of lines if a limit is provided.",
"This function skips the first 'offset' lines and then reads up to 'limit' lines if specified, or reads until the end of the file otherwise.",
"It's useful for partial reads, pagination, or previewing sections of large text files.",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/read_multiple_media_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rust_mcp_sdk::schema::{CallToolResult, schema_utils::CallToolError};

#[mcp_tool(
name = "read_multiple_media_files",
title="Read Multiple Media (Image/Audio) Files",
title="Read multiple media (Image/Audio) files",
description = concat!("Reads multiple image or audio files and returns their Base64-encoded contents along with corresponding MIME types. ",
"This method is more efficient than reading files individually. ",
"The max_bytes argument could be used to enforce an upper limit on the size of a file to read ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/read_multiple_text_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::Path;

#[mcp_tool(
name = "read_multiple_text_files",
title="Read Multiple Text Files",
title="Read multiple text files",
description = concat!("Read the contents of multiple text files simultaneously as text. ",
"This is more efficient than reading files one by one when you need to analyze ",
"or compare multiple files. Each file's content is returned with its ",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/search_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rust_mcp_sdk::schema::{CallToolResult, schema_utils::CallToolError};
use crate::fs_service::FileSystemService;
#[mcp_tool(
name = "search_files",
title="Search Files",
title="Search files",
description = concat!("Recursively search for files and directories matching a pattern. ",
"Searches through all subdirectories from the starting path. The search is case-insensitive ",
"and matches partial names. Returns full paths to all matching items.",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/search_files_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rust_mcp_sdk::schema::{CallToolResult, schema_utils::CallToolError};
use std::fmt::Write;
#[mcp_tool(
name = "search_files_content",
title="Move Files Content",
title="Move files content",
description = concat!("Searches for text or regex patterns in the content of files matching matching a GLOB pattern.",
"Returns detailed matches with file path, line number, column number and a preview of matched text.",
"By default, it performs a literal text search; if the 'is_regex' parameter is set to true, it performs a regular expression (regex) search instead.",
Expand Down
6 changes: 3 additions & 3 deletions src/tools/tail_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use rust_mcp_sdk::{

use crate::fs_service::FileSystemService;

// head_file
// tail_file
#[mcp_tool(
name = "head_file",
title="Head file",
name = "tail_file",
title="Tail file",
description = concat!("Reads and returns the last N lines of a text file.",
"This is useful for quickly previewing file contents without loading the entire file into memory.",
"If the file has fewer than N lines, the entire file will be returned.",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/write_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rust_mcp_sdk::schema::{CallToolResult, schema_utils::CallToolError};
use crate::fs_service::FileSystemService;
#[mcp_tool(
name = "write_file",
title="Write File",
title="Write file",
description = concat!("Create a new file or completely overwrite an existing file with new content. ",
"Use with caution as it will overwrite existing files without warning. ",
"Handles text content with proper encoding. Only works within allowed directories."),
Expand Down
2 changes: 1 addition & 1 deletion src/tools/zip_unzip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::fs_service::FileSystemService;

#[mcp_tool(
name = "zip_files",
title="Zip Files",
title="Zip files",
description = concat!("Creates a ZIP archive by compressing files. ",
"It takes a list of files to compress and a target path for the resulting ZIP file. ",
"Both the source files and the target ZIP file should reside within allowed directories."),
Expand Down
38 changes: 37 additions & 1 deletion tests/test_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod common;
use common::setup_service;
use rust_mcp_filesystem::tools::*;
use rust_mcp_sdk::schema::{ContentBlock, schema_utils::CallToolError};
use std::fs;
use std::{collections::HashSet, fs};

#[tokio::test]
async fn test_create_directory_new_directory() {
Expand Down Expand Up @@ -129,5 +129,41 @@ async fn test_create_directory_invalid_path() {
assert!(matches!(err, CallToolError { .. }));
}

// Github Issue #54
// https://github.com/rust-mcp-stack/rust-mcp-filesystem/issues/54
#[tokio::test]
async fn ensure_tools_duplication() {
let mut names = HashSet::new();
let mut duplicate_names = vec![];

let mut titles = HashSet::new();
let mut duplicate_titles = vec![];

let mut descriptions = HashSet::new();
let mut duplicate_descriptions = vec![];

for t in FileSystemTools::tools() {
if !names.insert(t.name.to_string()) {
duplicate_names.push(t.name.to_string());
}

if let Some(title) = t.title {
if !titles.insert(title.to_string()) {
duplicate_titles.push(title.to_string());
}
}

if let Some(description) = t.description {
if !descriptions.insert(description.to_string()) {
duplicate_descriptions.push(description.to_string());
}
}
}

assert_eq!(duplicate_names.join(","), "");
assert_eq!(duplicate_titles.join(","), "");
assert_eq!(duplicate_descriptions.join(","), "");
}

#[tokio::test]
async fn adhoc() {}