Support glob pattern in search_files tool (#745)
Co-authored-by: Adam Jones <adamj+git@anthropic.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Adam Jones <adamj@anthropic.com>
This commit is contained in:
parent
d381cf1ffd
commit
fd886fac9c
4 changed files with 14 additions and 14 deletions
|
|
@ -145,12 +145,12 @@ The server's directory access control follows this flow:
|
||||||
- Fails if destination exists
|
- Fails if destination exists
|
||||||
|
|
||||||
- **search_files**
|
- **search_files**
|
||||||
- Recursively search for files/directories
|
- Recursively search for files/directories that match or do not match patterns
|
||||||
- Inputs:
|
- Inputs:
|
||||||
- `path` (string): Starting directory
|
- `path` (string): Starting directory
|
||||||
- `pattern` (string): Search pattern
|
- `pattern` (string): Search pattern
|
||||||
- `excludePatterns` (string[]): Exclude any patterns. Glob formats are supported.
|
- `excludePatterns` (string[]): Exclude any patterns.
|
||||||
- Case-insensitive matching
|
- Glob-style pattern matching
|
||||||
- Returns full paths to matches
|
- Returns full paths to matches
|
||||||
|
|
||||||
- **directory_tree**
|
- **directory_tree**
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ describe('Lib Functions', () => {
|
||||||
|
|
||||||
const result = await searchFilesWithValidation(
|
const result = await searchFilesWithValidation(
|
||||||
testDir,
|
testDir,
|
||||||
'test',
|
'*test*',
|
||||||
allowedDirs,
|
allowedDirs,
|
||||||
{ excludePatterns: ['*.log', 'node_modules'] }
|
{ excludePatterns: ['*.log', 'node_modules'] }
|
||||||
);
|
);
|
||||||
|
|
@ -346,7 +346,7 @@ describe('Lib Functions', () => {
|
||||||
|
|
||||||
const result = await searchFilesWithValidation(
|
const result = await searchFilesWithValidation(
|
||||||
testDir,
|
testDir,
|
||||||
'test',
|
'*test*',
|
||||||
allowedDirs,
|
allowedDirs,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
@ -370,7 +370,7 @@ describe('Lib Functions', () => {
|
||||||
|
|
||||||
const result = await searchFilesWithValidation(
|
const result = await searchFilesWithValidation(
|
||||||
testDir,
|
testDir,
|
||||||
'test',
|
'*test*',
|
||||||
allowedDirs,
|
allowedDirs,
|
||||||
{ excludePatterns: ['*.backup'] }
|
{ excludePatterns: ['*.backup'] }
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -277,9 +277,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||||
name: "search_files",
|
name: "search_files",
|
||||||
description:
|
description:
|
||||||
"Recursively search for files and directories matching a pattern. " +
|
"Recursively search for files and directories matching a pattern. " +
|
||||||
"Searches through all subdirectories from the starting path. The search " +
|
"The patterns should be glob-style patterns that match paths relative to the working directory. " +
|
||||||
"is case-insensitive and matches partial names. Returns full paths to all " +
|
"Use pattern like '*.ext' to match files in current directory, and '**/*.ext' to match files in all subdirectories. " +
|
||||||
"matching items. Great for finding files when you don't know their exact location. " +
|
"Returns full paths to all matching items. Great for finding files when you don't know their exact location. " +
|
||||||
"Only searches within allowed directories.",
|
"Only searches within allowed directories.",
|
||||||
inputSchema: zodToJsonSchema(SearchFilesArgsSchema) as ToolInput,
|
inputSchema: zodToJsonSchema(SearchFilesArgsSchema) as ToolInput,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -367,14 +367,14 @@ export async function searchFilesWithValidation(
|
||||||
await validatePath(fullPath);
|
await validatePath(fullPath);
|
||||||
|
|
||||||
const relativePath = path.relative(rootPath, fullPath);
|
const relativePath = path.relative(rootPath, fullPath);
|
||||||
const shouldExclude = excludePatterns.some(excludePattern => {
|
const shouldExclude = excludePatterns.some(excludePattern =>
|
||||||
const globPattern = excludePattern.includes('*') ? excludePattern : `**/${excludePattern}/**`;
|
minimatch(relativePath, excludePattern, { dot: true })
|
||||||
return minimatch(relativePath, globPattern, { dot: true });
|
);
|
||||||
});
|
|
||||||
|
|
||||||
if (shouldExclude) continue;
|
if (shouldExclude) continue;
|
||||||
|
|
||||||
if (entry.name.toLowerCase().includes(pattern.toLowerCase())) {
|
// Use glob matching for the search pattern
|
||||||
|
if (minimatch(relativePath, pattern, { dot: true })) {
|
||||||
results.push(fullPath);
|
results.push(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue