filesystem: search_files does not expand non-wildcard excludePatterns like directory_tree does
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 72/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- node.js, typescript
Hướng nghiên cứu
Đọc searchFilesWithValidation trong src/filesystem/lib.ts cùng với buildTree trong src/filesystem/server.ts để so sánh cách chúng khớp với excludePatterns. Bổ sung kiểm thử trong src/filesystem/__tests__/lib.test.ts và src/filesystem/__tests__/server-tools.test.ts cho các mục loại trừ không có đường dẫn ở thư mục cấp cao nhất và thư mục lồng nhau. Công việc hoàn tất khi search_files bỏ qua các cây con thư mục khớp và hoạt động giống directory_tree.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
While auditing src/filesystem on v2.0.0 (origin/main) following the #4857 spec refactor, I found a behavioral mismatch in how excludePatterns is evaluated between directory_tree (src/filesystem/server.ts) and search_files (src/filesystem/lib.ts).
When an LLM or user passes a bare directory or file name in excludePatterns (for example, ["node_modules", ".git"]), directory_tree excludes both the directory and its entire subtree, whereas search_files still traverses into the excluded directory and returns all files inside it.
Server & Environment
- Server:
filesystem(@modelcontextprotocol/server-filesystemv2.0.0/origin/main) - Files:
src/filesystem/server.ts(buildTree) vs.src/filesystem/lib.ts(searchFilesWithValidation) - Protocol era / transport: Both
2026-07-28and2025-eraoverstdio/ in-memory client transport
Reproduction / Root Cause in v2/main
- In
directory_tree(src/filesystem/server.ts, lines 515–529),buildTreechecks whether an exclusion pattern contains*. If it does not, it automatically expands the pattern to match nested paths and subtrees (**/${pattern}and**/${pattern}/**), and skips recursing into the excluded directory:
const shouldExclude = excludePatterns.some((pattern) => {
if (pattern.includes("*")) {
return minimatch(relativePath, pattern, { dot: true });
}
// For files: match exact name or as part of path
// For directories: match as directory path
return (
minimatch(relativePath, pattern, { dot: true }) ||
minimatch(relativePath, `**/${pattern}`, { dot: true }) ||
minimatch(relativePath, `**/${pattern}/**`, { dot: true })
);
});
if (shouldExclude) continue;
- In
search_files(src/filesystem/lib.ts, lines 397–413),searchFilesWithValidationevaluatesminimatch(relativePath, excludePattern, { dot: true })directly without the non-wildcard expansion:
const relativePath = path.relative(rootPath, fullPath);
const shouldExclude = excludePatterns.some((excludePattern) =>
minimatch(relativePath, excludePattern, { dot: true }),
);
if (shouldExclude) continue;
What happens when a caller passes excludePatterns: ["node_modules"] or ["sub"]:
- At
node_modules(top-level):relativePathis"node_modules".minimatch("node_modules", "node_modules")istrue, soif (shouldExclude) continueskips recursing into top-levelnode_modules! - At
packages/app/node_modules(nested directory):relativePathis"packages/app/node_modules".minimatch("packages/app/node_modules", "node_modules")isfalse!search_filesenterspackages/app/node_modulesand traverses every file inside it. - When
excludePatterns: ["node_modules/*"]or["**/node_modules"](without trailing/**) is passed: Even if a pattern matches files inside a directory,search_filesstill wastes I/O recursing unless the directory entry itself matchesshouldExclude.
Expected vs. Actual Behavior
- Expected: Passing
excludePatterns: ["node_modules", ".git"](or a bare filename/directory name without*) tosearch_filesshould behave identically todirectory_tree: any nested directory or file matchingpattern,**/${pattern}, or**/${pattern}/**is excluded and its directory subtree is not traversed. - Actual:
directory_treeexcludes nestedpackages/app/node_modules, whilesearch_filestraverses intopackages/app/node_modulesand returns matches from inside it unless the caller explicitly writes**/node_modules/**.
Prompt to Reproduce Fix in the Agentic Workflow
Per CONTRIBUTING.md, here is the exact prompt to fix and test this in the factory workflow:
Unify `excludePatterns` matching between `directory_tree` (`src/filesystem/server.ts`) and `search_files` (`src/filesystem/lib.ts`):
1. Extract a shared helper (or update `searchFilesWithValidation` in `src/filesystem/lib.ts` to match `buildTree` in `src/filesystem/server.ts`) so that when an entry in `excludePatterns` does not contain `*`, it matches `minimatch(relativePath, pattern, { dot: true }) || minimatch(relativePath, `**/${pattern}`, { dot: true }) || minimatch(relativePath, `**/${pattern}/**`, { dot: true })`.
2. Add a protocol-level test in `src/filesystem/__tests__/server-tools.test.ts` (and unit test in `src/filesystem/__tests__/lib.test.ts`) verifying that `search_files` with a bare name in `excludePatterns` (e.g. `excludePatterns: ["ignored_dir"]`) excludes both top-level `ignored_dir/file.txt` and nested `nested/ignored_dir/file.txt`, matching `directory_tree`'s behavior.
3. Run `npm run format` and `npm run local:gate`.
- Ngôn ngữ chính
- TypeScript
- Star
- 91.4k
- Fork
- 11.8k
- Merge trung bình
- 7 giờ 26 phút
- Pull request đã merge (30 ngày)
- 130
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/servers
-
git: README should state plainly that without --repository every reachable repository is in scopeĐang mởdocumentation server-git v2
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 84/100
modelcontextprotocol/servers#5225 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
chore v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
modelcontextprotocol/servers#5223 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
modelcontextprotocol/servers#5217 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 79/100
modelcontextprotocol/servers#5215 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation server-git server-time v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
modelcontextprotocol/servers#5213 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của modelcontextprotocol/servers
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
db-ux-design-system/core-web#8613 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug:new
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
callstackincubator/simlock#934 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Log page not working after errorĐang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
gchq/LD-Explorer#286 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
foxglove/mcap#1907 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày