@jungho-dev/fs-mcp
by jungho-dev
README.md
# @jungho-dev/fs-mcp
## Overview
`@jungho-dev/fs-mcp` is a stdio-based Model Context Protocol server for local file work, batched
search, exact block editing, and essential git workflows.
This package is the MCP server runtime. It is not a VS Code extension bundle, does not require a
specific AI client, and does not open a network listener. Any MCP-capable client that can launch a
stdio command can use it, including Codex, Claude, Cline, Roo, Cursor, Windsurf, VS Code MCP clients,
Gemini CLI, and GitHub Copilot.
The current runtime does not include a SQLite sidecar, context-index store, or MCP resource catalog.
Resource and resource-template handlers intentionally return empty lists for client compatibility.
## Measured Performance And Token Savings
The practical baseline for AI file work is often repeated shell calls that each pay process and tool-call overhead.
Current benchmarks show where `fs-mcp` reduces that overhead while keeping full payloads available to the client.
| Scenario | `fs-mcp` path | Baseline | Measured effect |
|----------|---------------|----------|-----------------|
| Read 12 files, 4 KB each | One `file-read` batch: `3.11 ms` avg, `1.86 ms` median | Sequential PowerShell reads: `2,617.42 ms` avg, `2,579.75 ms` median | About `842x` faster by average time and `1,387x` faster by median time |
| Write 20 files, 4 KB each | `args_path` reference: `140` transport chars, `35` token est | Inline JSON payload: `82,911` transport chars, `20,728` token est | `99.83%` fewer transport chars and `20,693` estimated tokens avoided |
| Normalize one 128 KB text result | Visible display: `498` chars; duplicated `content` slots: `817` chars | Raw text body: `131,072` chars | Full text stays in `data.content` while repeated visible text is kept to a preview |
Numbers above were generated on `2026-05-24` from this checkout with seven runs per timed scenario:
```bash
bun tests/scripts/performance-benchmark.mjs
bun tests/scripts/write-files-args-path-benchmark.mjs
```
Token estimates use the project heuristic of `4` characters per token. Actual model billing depends on the client and
whether it forwards only `content[0].text` or also injects `structuredContent` into model context.
## Installation
Install the package globally with npm:
```bash
npm install -g @jungho-dev/fs-mcp
```
Or install it globally with Bun:
```bash
bun add -g @jungho-dev/fs-mcp
```
## MCP Client Configuration
Use this server command for MCP clients that accept JSON-style `mcpServers` configuration:
```json
{
"mcpServers": {
"fs-mcp": {
"command": "fs-mcp",
"args": []
}
}
}
```
Codex uses TOML instead of JSON. Add the same command to `~/.codex/config.toml` after global install:
```toml
[mcp_servers.fs-mcp]
enabled = true
startup_timeout_sec = 60.0
tool_timeout_sec = 120.0
command = "fs-mcp"
args = []
```
If a client cannot resolve global binaries, set `command` to the absolute `fs-mcp` executable path.
## Current Public Tool Surface
The current source and compiled runtime expose 24 public tools that mirror the rust-fs-mcp surface. Tool names
are intentionally short, hyphenated, and stable for clients that cache MCP catalogs.
| Domain | Tools | Purpose |
|--------|-------|---------|
| Filesystem | `file-read`, `file-read-line-range`, `file-write`, `path-stat` | Read, line-range-read, write, and inspect files. |
| Directories | `dir-list`, `dir-create` | List directory trees and create directories. |
| File operations | `path-copy`, `path-move`, `path-remove`, `file-edit`, `file-edit-lines` | Copy, move, remove, exact-edit, and line-range-edit files or directories. |
| Inspect | `fs-inspect` | Bundle count-files, search, json-pick, snippet, and git-status lookups into one read-only call. |
| Search | `fs-search` | Run direct ripgrep-compatible regex scans. |
| Web | `web-fetch`, `web-render`, `web-extract`, `download-to-file` | Fetch URLs, render JS/SPA pages through obscura, extract held HTML, and download files. |
| Git | `git-set-workdir`, `git-status`, `git-diff`, `git-show`, `git-add`, `git-commit`, `git-amend` | Pin repo state, inspect changes, stage, commit, and amend. |
`src/schemas/schemas-git.ts` contains schemas for additional git operations, but `src/tools/tools-git.ts`
exports only the essential git set above in this version. Config tools and process controls are outside the current
public catalog.
## Main Capabilities
- Batch-first filesystem reads, writes, listings, metadata checks, directory creation, copying, moving,
deletion, exact block replacement, and 1-based line range edits.
- `fs-inspect` composite lookups that bundle count-files, search, json-pick, snippet, and git-status into one
round-trip.
- Direct ripgrep-compatible regex search through `fs-search`.
- SSRF-guarded web tier: `web-fetch` for static pages, `web-render` for JS/SPA pages via the obscura headless
browser, `web-extract` for offline HTML conversion, and `download-to-file` for sandboxed downloads.
- Optional DOCX text extraction for content searches when the target inputs or patterns include `.docx`.
- Essential git session workflows for repository pinning, status, diff, show, staging, and commit.
- Normalized tool responses with a visible display block, machine-readable `structuredContent`, and compact
`_meta.fsMcpResult` metadata.
## Batch-First Tool Use
`SERVER_INSTRUCTIONS` and batch-capable tool descriptions tell clients to collapse repeated same-kind work into
one multi-item call. This applies to:
- File reads through `paths` or `items`.
- Directory and file operations through `items` or `paths` arrays.
- Search work through `fs-search.items`.
- Web work through `web-fetch.items`, `web-extract.items`, and `download-to-file.items`.
Large arguments can be moved into a UTF-8 JSON file and passed with `args_path`. Inline fields supplied beside
`args_path` override fields from the referenced JSON object. Large text payloads can also use path-backed fields
such as `content_path`, `old_string_path`, `new_string_path`, `pattern_path`, and `messagePath`.
`file-read`, `file-read-line-range`, `dir-list`, and `path-stat` accept `allowMissing=true` so exploratory
candidate reads can return missing local paths as non-error results.
## Runtime Notes
The full source catalog exposes `24` public tools. Serialized catalog size is build-dependent; measure it from the compiled `out` catalog before using it for token or latency comparisons.
Runtime behavior:
- Tool catalogs are assembled once during server creation.
- Zod-to-JSON-schema conversion is lazy-cached per tool entry.
- Tool calls resolve `args_path`, `args_offset`, and `args_length` before controller validation.
- `fs-search` has no implicit `maxResults` cap. Set `maxResults` explicitly when a bounded scan is needed.
- The fixed compact envelope keeps the body once in `data.content`; it does not add a `data.text` copy.
- Stdio filtering captures accidental console output before it can corrupt MCP JSON-RPC frames.
## Runtime Configuration
Runtime configuration is in memory only. The server does not create a first-run config file.
Internal runtime configuration keys are:
- `allowedDirectories`
- `blockedCommands`
- `defaultShell`
Allowed directories, blocked commands, and default shell are runtime-only values; no environment variable changes their behavior.
## Client Compatibility
- Client metadata is captured during initialization and can also be refreshed from call metadata.
- Git calls run inside a client-scoped git session key.
- Claude and Codex keep standard server-side notification behavior.
- Gemini CLI and GitHub Copilot suppress server-side JSON-RPC notifications for compatibility.
- Resource and resource-template list handlers return empty lists so probing clients initialize cleanly.
## Repository Structure
```text
project root/
|-- src/
| |-- assets/ shared readers, type declarations, and cross-domain utilities
| |-- controllers/ MCP request handlers and batch response helpers
| |-- cores/ runtime, stdio transport, server assembly, and response normalization
| |-- features/ config, edit, filesystem, git, process, and search behavior
| |-- schemas/ request argument validation schemas
| `-- tools/ tool catalog entries and dispatcher
|-- tests/ contract tests, smoke tests, fixtures, and verification scripts
`-- out/ compiled runtime published to npm
```
## Response Shape
Every dispatched tool result is normalized by `src/cores/responses/responses-tool-result.ts`.
- Visible `content[0].text` is generated by `src/cores/responses/responses-tool-display.ts`.
- The default visible rows are `tool`, `items`, `status`, `duration`, `tokens`, `contents`, and `structuredText`.
- `tokens` uses a lightweight character-based estimate over content text plus serialized structured content.
- `structuredContent` stores schema version, tool name, status, duration, error detail, original normalized content,
and original structured payload.
- The fixed compact envelope keeps the body once in `data.content`. Batch per-item results carry only
`structuredContent` and `isError`, and echoed input strings above 256 bytes become `<N bytes elided>`.
- `_meta.fsMcpResult` stores compact status, duration, content type, error, schema, and tool metadata.
- Already normalized results are not wrapped again; the visible display text is regenerated.
## Development
Current development checks use Bun:
```bash
bun x tsc --noEmit
bun tests/run-all-tests.js
bun tests/scripts/performance-benchmark.mjs
bun tests/scripts/write-files-args-path-benchmark.mjs
```
Useful scoped checks:
```bash
bun tests/scripts/scripts-verify-release-shape.mjs
bun tests/scripts/scripts-verify-tool-surface.mjs
bun tests/scripts/scripts-verify-optimization-reports.mjs
bun tests/scripts/scripts-verify-doc-sync.mjs
```
`tests/run-all-tests.js` rebuilds `out`, then runs contract and smoke tests.
Verification scripts under `tests/scripts/` check release shape, source boundaries, optimization reports, and the
compiled tool surface.
## Documentation
- English README: `README.md`
- Korean README: `readme-ko.md`
- English architecture: `architecture.md`
- Korean architecture: `architecture-ko.md`
- Changelog: `changelog.md`
## Packaging Notes
The npm package exposes the `fs-mcp` binary through `out/index.mjs`. Runtime version metadata is read from the
package root `package.json`. The package file allowlist includes `out`, release documentation, and changelog files.
Source files, tests, fixtures, and local runtime artifacts remain development-only surfaces.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues