filesystem: search_files does not expand non-wildcard excludePatterns like directory_tree does
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 72/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- node.js, typescript
調査の方向性
src/filesystem/lib.ts の searchFilesWithValidation と src/filesystem/server.ts の buildTree を読み、excludePatterns の照合方法を比較してください。トップレベルとネストされたディレクトリで、パスを含まない除外指定を扱うテストを src/filesystem/__tests__/lib.test.ts と src/filesystem/__tests__/server-tools.test.ts に追加してください。search_files が一致するディレクトリのサブツリーをスキップし、directory_tree と同じ動作をすれば完了です。
索引モデルが issue の本文から書いたものです。
説明
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`.
- 主要言語
- TypeScript
- スター
- 91.4k
- フォーク
- 11.8k
- 平均マージ
- 7時間 36分
- マージ済み PR(30日)
- 126
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
modelcontextprotocol/servers のほかの issue
-
bug v2
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
modelcontextprotocol/servers#5217 ·
メンテナーはふだん 1 日以内に返信
-
bug v2
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
modelcontextprotocol/servers#5215 ·
メンテナーはふだん 1 日以内に返信
-
documentation server-git server-time v2
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
modelcontextprotocol/servers#5213 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
documentation v2
難易度 1/5 1〜3時間 初心者へのやさしさ 78/100
modelcontextprotocol/servers#5212 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
documentation v2
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
modelcontextprotocol/servers#5211 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
modelcontextprotocol/servers の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
chaitin/MonkeyCode#1437 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 69/100
carbon-design-system/carbon-ai-chat#2615 ·
メンテナーはふだん 1 日以内に返信
-
e2e-failure ready-to-code
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
redhat-developer/rhdh-plugin-export-overlays#4486 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
[Bug]: fileUploadMatrix.test.ts URL case does a real DNS lookup and fails offline対応中かも @r2jaff が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
ComposioHQ/composio#5054 ·
メンテナーはふだん 1 日以内に返信