Skip to main content
Glama

find_files

Search for files matching a pattern within allowed directories and return their paths, enabling efficient file discovery and organization.

Instructions

在允許的目錄中找尋所有符合檔名模式的檔案並標示其檔案路徑

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filePatternYes
excludeDirsNo

Implementation Reference

  • main.ts:479-509 (registration)
    Registration of the 'find_files' tool, including inline Zod schema for input validation and thin handler that delegates to FileSearchTool for actual searching.
    server.tool("find_files",
        "在允許的目錄中找尋所有符合檔名模式的檔案並標示其檔案路徑",
        {
            filePattern: z.string(),
            excludeDirs: z.array(z.string()).optional()
        },
        async ({ filePattern, excludeDirs = ['node_modules', '.git', 'dist', 'bin', 'obj'] }) => {
            try {
                // 獲取允許的目錄列表
                const allowedDirs = await FileSearchTool.getAllowedDirectories();
    
                // 檢查是否有允許的目錄
                if (allowedDirs.length === 0) {
                    return {
                        content: [{ type: "text", text: '錯誤:未提供允許的目錄參數。請在啟動時指定至少一個允許的目錄。' }]
                    };
                }
    
                // 在允許的目錄中搜尋檔案
                const result = await FileSearchTool.searchFilesInAllowedDirs(allowedDirs, filePattern, excludeDirs);
    
                return {
                    content: [{ type: "text", text: result }]
                };
            } catch (error) {
                return {
                    content: [{ type: "text", text: `搜尋檔案失敗: ${error instanceof Error ? error.message : "未知錯誤"}` }]
                };
            }
        }
    );
  • Core helper method called by the tool handler to search for files matching the pattern across allowed directories, formats and returns the results as a string.
    public static async searchFilesInAllowedDirs(
        allowedDirs: string[],
        filePattern: string,
        excludeDirs: string[] = ['node_modules', '.git', 'dist', 'bin', 'obj']
    ): Promise<string> {
        try {
            if (!filePattern) {
                return '錯誤: 請提供檔名模式';
            }
                        // 檢查是否有允許的目錄
                        if (allowedDirs.length === 0) {
                            return '錯誤:未提供允許的目錄參數。請在啟動時指定至少一個允許的目錄。';
                        }
    
            let allResults: string[] = [];
            
            for (const dir of allowedDirs) {
                // 檢查目錄是否存在
                if (!fs.existsSync(dir)) {
                    continue;
                }
                
                const results = await this.searchFiles(dir, filePattern, excludeDirs);
                allResults = allResults.concat(results);
            }
    
            if (allResults.length === 0) {
                return `未找到符合模式 "${filePattern}" 的檔案`;
            }
    
            // 將搜尋結果格式化為字串
            const formattedResults = allResults
                .map((filePath, index) => `${index + 1}. ${filePath}`)
                .join('\n');
    
            return `找到 ${allResults.length} 個符合模式 "${filePattern}" 的檔案:\n${formattedResults}`;
        } catch (error) {
            return `搜尋檔案失敗: ${error instanceof Error ? error.message : '未知錯誤'}`;
        }
    }
  • Recursive file search implementation that traverses directories, skips excluded dirs, and collects files matching the pattern using a regex converted from wildcard.
    public static async searchFiles(
        rootDir: string, 
        filePattern: string,
        excludeDirs: string[] = []
    ): Promise<string[]> {
        const readdir = util.promisify(fs.readdir);
        const stat = util.promisify(fs.stat);
        const results: string[] = [];
    
        // 將文件模式轉換為正則表達式
        const patternRegex = this.convertPatternToRegex(filePattern);
    
        // 遞迴搜尋函數
        async function searchDir(dir: string) {
            try {
                // 檢查是否有權限讀取目錄
                await util.promisify(fs.access)(dir, fs.constants.R_OK);
                
                const files = await readdir(dir);
                
                for (const file of files) {
                    // 跳過排除的目錄
                    if (excludeDirs.includes(file)) {
                        continue;
                    }
                    
                    const fullPath = path.join(dir, file);
                    const fileStat = await stat(fullPath);
                    
                    if (fileStat.isDirectory()) {
                        // 遞迴搜尋子目錄
                        await searchDir(fullPath);
                    } else if (patternRegex.test(file)) {
                        // 檔名符合模式
                        results.push(fullPath);
                    }
                }
            } catch (error) {
                // 忽略讀取目錄失敗的錯誤
                console.error(`無法讀取目錄 ${dir}: ${error instanceof Error ? error.message : '未知錯誤'}`);
            }
        }
    
        // 開始搜尋
        await searchDir(rootDir);
        return results;
    }
  • Helper method to retrieve allowed directories from command-line arguments, returns empty array if none provided.
    public static async getAllowedDirectories(): Promise<string[]> {
        // 從命令行參數獲取允許的目錄(從第2個參數開始,因為第1個是Node路徑,第2個是腳本路徑)
        const args = process.argv.slice(2);
        
        // 如果命令行中有額外參數,則這些參數被視為允許的目錄
        if (args && args.length > 0) {
            return args;
        }
        
        // 因沒有提供命令行參數,因此回報錯誤
        console.error('錯誤:未提供允許的目錄參數。請在啟動時指定至少一個允許的目錄。');
        console.error('使用範例:');
        console.error('node [dist路徑]/main.js "C:\\path\\to\\allowed\\directory1" "C:\\path\\to\\allowed\\directory2"');
        
        // 返回空陣列,表示沒有允許的目錄
        return [];
    }
  • Utility method to convert simple wildcard patterns (*, ?) to case-insensitive regex for filename matching.
    private static convertPatternToRegex(pattern: string): RegExp {
        // 轉義特殊字符
        let regexPattern = pattern
            .replace(/[.+^${}()|[\]\\]/g, '\\$&')
            .replace(/\*/g, '.*')  // * 轉換為 .*
            .replace(/\?/g, '.');  // ? 轉換為 .
        
        return new RegExp(`^${regexPattern}$`, 'i');  // 不區分大小寫
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the tool finds and marks file paths, implying a read-only operation, but doesn't mention whether it's recursive, what 'allowed directories' means, performance characteristics, error handling, or output format. For a tool with 2 parameters and no annotation coverage, this leaves significant gaps in understanding its behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence in Chinese that directly states the tool's function without unnecessary words. It's appropriately sized and front-loaded with the core purpose, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 2 parameters with 0% schema coverage, no annotations, and no output schema, the description is incomplete. It doesn't explain what 'allowed directories' are, how patterns work, what the output looks like, or any behavioral details like recursion depth or error conditions. For a file search tool with undocumented parameters, more context is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for undocumented parameters. It mentions '檔名模式' (filename pattern) which maps to 'filePattern', and implies directory filtering but doesn't explain 'excludeDirs' or provide examples of patterns. The description adds minimal semantic context beyond the bare parameter names, failing to fully compensate for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: '在允許的目錄中找尋所有符合檔名模式的檔案並標示其檔案路徑' translates to 'find all files matching a filename pattern in allowed directories and mark their file paths'. This specifies the verb (find), resource (files), and scope (allowed directories). However, it doesn't explicitly differentiate from sibling tools like 'search_code' or 'fileRead', which might have overlapping functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It mentions 'allowed directories' but doesn't specify what these are or how they differ from other file-related tools in the sibling list. There's no mention of prerequisites, limitations, or comparison to tools like 'search_code' or 'fileRead'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/GonTwVn/GonMCPtool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server