webdav_search_files
Search WebDAV file systems using glob patterns to find specific files and directories, with exclusion options to filter results.
Instructions
Search for files and directories using glob patterns with exclusion support
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| excludePatterns | No | Array of glob patterns to exclude from search results | |
| path | No | Starting directory for the search | / |
| pattern | Yes | Glob pattern to match files (e.g., "*.txt", "**/*.js", "config.*") |
Implementation Reference
- src/handlers/tool-handlers.ts:530-574 (handler)Full MCP tool definition including registration, input schema validation with Zod, and handler logic that delegates search to WebDAVService.searchFiles and formats the response.server.tool( "webdav_search_files", "Search for files and directories using glob patterns with exclusion support", { path: z.string().optional().default("/").describe( "Starting directory for the search", ), pattern: z.string().describe( 'Glob pattern to match files (e.g., "*.txt", "**/*.js", "config.*")', ), excludePatterns: z.array(z.string()).optional().default([]).describe( "Array of glob patterns to exclude from search results", ), }, async ({ path, pattern, excludePatterns }) => { try { const results = await webdavService.searchFiles( path, pattern, excludePatterns, ); const message = results.length > 0 ? `Found ${results.length} items matching "${pattern}":\n\n${ results.join("\n") }` : `No items found matching "${pattern}"`; return { content: [{ type: "text", text: message, }], }; } catch (error) { return { content: [{ type: "text", text: `Error searching files: ${(error as Error).message}`, }], isError: true, }; } }, );
- WebDAVService.searchFiles method: orchestrates recursive file search starting from given path using glob patterns and exclusions.async searchFiles( path: string = "/", pattern: string, excludePatterns: string[] = [], ): Promise<string[]> { const fullPath = this.getFullPath(path); logger.debug(`Searching for files: ${fullPath}`, { pattern, excludePatterns, }); try { const results: string[] = []; await this._searchRecursive( fullPath, pattern, path, excludePatterns, results, ); logger.debug(`Search completed: ${fullPath}`, { results: results.length, }); return results; } catch (error) { logger.error(`Error searching files in ${fullPath}:`, error); throw new Error(`Failed to search files: ${(error as Error).message}`); } }
- Private recursive implementation that lists directories, applies minimatch for matching and excluding paths, collects matching relative paths.private async _searchRecursive( currentPath: string, pattern: string, basePath: string, excludePatterns: string[], results: string[], ): Promise<void> { try { const items = await this.list(currentPath); for (const item of items) { const relativePath = item.filename.replace( this.rootPath === "/" ? "" : this.rootPath, "", ); // Check if this item should be excluded const shouldExclude = excludePatterns.some((excludePattern) => minimatch(relativePath, excludePattern, { dot: true }) ); if (shouldExclude) { continue; } // Check if this item matches the search pattern if (minimatch(relativePath, pattern, { dot: true })) { results.push(relativePath); } // If it's a directory, search recursively if (item.type === "directory") { await this._searchRecursive( item.filename, pattern, basePath, excludePatterns, results, ); } } } catch (error) { logger.warn(`Warning: Could not access directory ${currentPath}:`, error); } }