test(filesystem): bring index.ts from 0% to 98.5% coverage (per #4474 server-by-server plan) - #4690
Open
Parker-Fawcett wants to merge 2 commits into
Open
Conversation
… writing literal filenames On POSIX, a path like C:\Users\me\notes\file.md is not absolute, so validatePath() sent it down the relative-path branch and path.resolve() placed it inside the allowed root as a single entry literally named 'C:\Users\me\notes\file.md' (or created a C:/ directory tree). Callers saw success and only discovered the mistake when inspecting disk - reported in modelcontextprotocol#4686. validatePath() now rejects drive-letter forms (^[A-Za-z]:(?:[\\/]|$)) up front when process.platform is not win32, with an explicit access-denied error. The check is one-directional and platform-guarded so Windows behavior is untouched and POSIX paths are never rewritten (no modelcontextprotocol#3628 regression). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…, and roots flows index.ts was the only 0%-coverage file in server-filesystem: the entire MCP tool-registration layer (14 tools), every handler body, the argv-driven startup path, and the roots-protocol integration were untested. Per modelcontextprotocol#4474's per-server coverage plan, this adds a vitest suite that captures registerTool calls through a mocked McpServer so the real wiring (names, schemas, annotations) plus handler behavior are exercised without changing production code or exporting test-only helpers. Coverage of src/filesystem/index.ts: lines 0% -> 98.54%, statements 0% -> 98.51%, functions 0% -> 100%, branches 0% -> 94.28%. Server overall rises from 46% to 90.39%. Suite grows 158 -> 206 tests, all passing. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
src/filesystem/__tests__/index.test.ts(774 lines, 48 tests), covering the previously untestedsrc/filesystem/index.ts— the MCP tool-registration layer. Contributes the filesystem chunk of #4474 ("Write the missing tests, server by server — each server can be its own PR") and supplies data for its first task ("Audit current coverage per server").No production code is modified. The suite captures
registerTool(name, config, handler)calls through a mockedMcpServer, so the real wiring is asserted directly and handlers are invoked without exporting any test-only helpers or changing module structure.Server Details
Motivation and Context
#4474 asks for a ≥90% per-file coverage gate across servers. The audit baseline shows every TS server's
index.tsbootstrap/registration file sits at or near 0%, andserver-filesystemhad the largest such gap (~750 lines covering all 14 tools). This PR closes that gap for the repo's most-deployed reference server.Coverage audit baseline (current main, for the #4474 tracking comment):
What's covered
readOnlyHint/destructiveHint/idempotentHint) matching each tool's semantics.wx-flag call shape, edit_file apply vs dry-run, create_directory, list_directory, list_directory_with_sizes both sort modes + stat-failure fallback + summary, directory_tree recursion + glob/plain excludePatterns, move_file, search_files match/exclude/no-match, get_file_info formatting.vi.resetModules()), macOS-style symlink resolution to dual original/resolved entries, inaccessible-directory skipping, the all-inaccessible exit guard, and the fatal connect-failure path.How Has This Been Tested?
npm run buildstays clean; full workspace untouched outside the new test file.src/filesystem/index.ts: lines 0% → 98.54%, statements → 98.51%, functions → 100%, branches → 94.28%, clearing Bring all servers to the 90% per-file coverage gate; reintroduce the rule to AGENTS.md #4474's 90/90/90/90 gate. Server overall: 46.1% → 90.4%.Breaking Changes
None — test-only change.
Types of changes
Checklist
Additional context
Design notes for review:
fs/promisesis mocked wholesale following the existinglib.test.tspattern;lib.ts/path-utils.tsare intentionally not mocked so handler tests exercise real validation logic against the mock boundary.roots-utils.tsimportsfs.promises(from'fs'), so the'fs'partial mock shares the same promises stub — keeping roots flows deterministic without mocking roots-utils itself.argvbecause the real one runs at import time; it is ordered last sincevi.resetModules()duplicates captured registrations.