@@ -13,6 +13,7 @@ import os from 'os';
13
13
import { z } from "zod" ;
14
14
import { zodToJsonSchema } from "zod-to-json-schema" ;
15
15
import { diffLines , createTwoFilesPatch } from 'diff' ;
16
+ import { minimatch } from 'minimatch' ;
16
17
17
18
// Command line argument parsing
18
19
const args = process . argv . slice ( 2 ) ;
@@ -134,6 +135,7 @@ const MoveFileArgsSchema = z.object({
134
135
const SearchFilesArgsSchema = z . object ( {
135
136
path : z . string ( ) ,
136
137
pattern : z . string ( ) ,
138
+ excludePatterns : z . array ( z . string ( ) ) . optional ( ) . default ( [ ] )
137
139
} ) ;
138
140
139
141
const GetFileInfoArgsSchema = z . object ( {
@@ -183,6 +185,7 @@ async function getFileStats(filePath: string): Promise<FileInfo> {
183
185
async function searchFiles (
184
186
rootPath : string ,
185
187
pattern : string ,
188
+ excludePatterns : string [ ] = [ ]
186
189
) : Promise < string [ ] > {
187
190
const results : string [ ] = [ ] ;
188
191
@@ -191,11 +194,22 @@ async function searchFiles(
191
194
192
195
for ( const entry of entries ) {
193
196
const fullPath = path . join ( currentPath , entry . name ) ;
194
-
197
+
195
198
try {
196
199
// Validate each path before processing
197
200
await validatePath ( fullPath ) ;
198
201
202
+ // Check if path matches any exclude pattern
203
+ const relativePath = path . relative ( rootPath , fullPath ) ;
204
+ const shouldExclude = excludePatterns . some ( pattern => {
205
+ const globPattern = pattern . includes ( '*' ) ? pattern : `**/${ pattern } /**` ;
206
+ return minimatch ( relativePath , globPattern , { dot : true } ) ;
207
+ } ) ;
208
+
209
+ if ( shouldExclude ) {
210
+ continue ;
211
+ }
212
+
199
213
if ( entry . name . toLowerCase ( ) . includes ( pattern . toLowerCase ( ) ) ) {
200
214
results . push ( fullPath ) ;
201
215
}
@@ -522,7 +536,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
522
536
throw new Error ( `Invalid arguments for search_files: ${ parsed . error } ` ) ;
523
537
}
524
538
const validPath = await validatePath ( parsed . data . path ) ;
525
- const results = await searchFiles ( validPath , parsed . data . pattern ) ;
539
+ const results = await searchFiles ( validPath , parsed . data . pattern , parsed . data . excludePatterns ) ;
526
540
return {
527
541
content : [ { type : "text" , text : results . length > 0 ? results . join ( "\n" ) : "No matches found" } ] ,
528
542
} ;
@@ -544,9 +558,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
544
558
545
559
case "list_allowed_directories" : {
546
560
return {
547
- content : [ {
548
- type : "text" ,
549
- text : `Allowed directories:\n${ allowedDirectories . join ( '\n' ) } `
561
+ content : [ {
562
+ type : "text" ,
563
+ text : `Allowed directories:\n${ allowedDirectories . join ( '\n' ) } `
550
564
} ] ,
551
565
} ;
552
566
}
@@ -574,4 +588,4 @@ async function runServer() {
574
588
runServer ( ) . catch ( ( error ) => {
575
589
console . error ( "Fatal error running server:" , error ) ;
576
590
process . exit ( 1 ) ;
577
- } ) ;
591
+ } ) ;
0 commit comments