Skip to main content
Glama

search_files

Locate files and directories in your notes by searching recursively with a case-insensitive pattern, returning full paths for partial matches. Exclude specific glob patterns to refine results.

Instructions

Recursively search for files and directories matching a pattern in your notes directory. The search is case-insensitive and matches partial names. Returns full paths to all matching items. Great for finding notes when you don't know their exact location.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
excludePatternsNoGlob patterns to exclude from search results
patternYesThe pattern to search for in file and directory names

Implementation Reference

  • Main handler for 'search_files' tool: validates input, invokes searchFiles helper, formats relative paths, returns results or error.
    export async function handleSearchFiles(notesPath: string, args: SearchFilesArgs): Promise<ToolCallResult> { try { // Validate pattern is provided if (!args.pattern) { throw new Error("'pattern' parameter is required"); } // Always search in the notes directory const results = await searchFiles( notesPath, args.pattern, args.excludePatterns || [] ); if (results.length === 0) { return { content: [{ type: "text", text: "No files found matching the pattern." }] }; } // Format results as relative paths const formattedResults = results.map((filePath: string) => path.relative(notesPath, filePath) ); return { content: [{ type: "text", text: `Found ${results.length} files matching "${args.pattern}":\n\n${formattedResults.join('\n')}` }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Error searching files: ${errorMessage}` }], isError: true }; } }
  • Tool definition including input schema for 'search_files'.
    { name: "search_files", description: "Recursively search for files and directories matching a pattern in your notes directory. " + "The search is case-insensitive and matches partial names. Returns full paths to all " + "matching items. Great for finding notes when you don't know their exact location.", inputSchema: { type: "object", properties: { pattern: { type: "string", description: "The pattern to search for in file and directory names" }, excludePatterns: { type: "array", items: { type: "string" }, description: "Glob patterns to exclude from search results", default: [] } }, required: ["pattern"] }, },
  • Core recursive file search implementation using minimatch for exclusions, case-insensitive partial name matching.
    export async function searchFiles(rootPath: string, pattern: string, excludePatterns: string[] = []): Promise<string[]> { const results: string[] = []; // Normalize the search pattern for better matching const normalizedPattern = pattern.toLowerCase(); // Make sure the root path exists try { const rootStats = await fs.stat(rootPath); if (!rootStats.isDirectory()) { console.error(`Search root is not a directory: ${rootPath}`); return []; } } catch (error) { console.error(`Error accessing search root path ${rootPath}:`, error); return []; } async function search(currentPath: string): Promise<void> { try { // Read directory entries const entries = await fs.readdir(currentPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentPath, entry.name); try { // Check if path matches any exclude pattern const relativePath = path.relative(rootPath, fullPath); const shouldExclude = excludePatterns.some(pattern => { const globPattern = pattern.includes('*') ? pattern : `**/${pattern}/**`; return minimatch(relativePath, globPattern, { dot: true }); }); if (shouldExclude) { continue; } // Match the name (case-insensitive) if (entry.name.toLowerCase().includes(normalizedPattern)) { results.push(fullPath); } // Recursively search subdirectories if (entry.isDirectory()) { await search(fullPath); } } catch (error) { // Skip problematic entries console.error(`Error processing ${fullPath}:`, error); continue; } } } catch (error) { console.error(`Error reading directory ${currentPath}:`, error); } } // Start the search await search(rootPath); // Log the number of results found console.error(`Search found ${results.length} results for pattern "${pattern}" in ${rootPath}`); return results; }
  • Switch case registration dispatching 'search_files' tool calls to handleSearchFiles.
    case "search_files": return await handleSearchFiles(notesPath, args);
  • Import of handleSearchFiles handler from filesystem module for tool registration.
    import { ensureDirectory, initializeNotesDirectory, handleSearchFiles, handleReadNote, handleReadMultipleNotes, handleListDirectory, handleCreateDirectory, getFilesystemToolDefinitions } from './filesystem.js';

Other Tools

Related 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/mikeysrecipes/mcp-notes'

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