Token-efficient filesystem access for Claude — read, write, search, and analyze code without burning your context window
Quick Start · Features · Configuration · Tech Stack · Contributing
- Overview
- Features
- Demo
- Tech Stack
- Requirements
- Quick Start
- Configuration
- Packaging as a Desktop Extension
- How It Works
- Project Structure
- Documentation
- Security & Privacy
- Contributing
- License
- Author
Every time an LLM reads a whole file just to answer a small question, it burns thousands of tokens it didn't need. MCP Filesystem Agent is a Model Context Protocol server that gives Claude 22 purpose-built file operations — preview reads, chunked pagination, AST-based code search, dry-run edits — so it gets exactly the context it needs and nothing more.
The problem: naive "read the whole file" tool-use patterns don't scale past a few hundred lines before they eat your context budget.
The solution: structured, scoped operations — read_file(preview_lines=50) instead of dumping 2,000 lines; search_code_structure() instead of reading five files to find one function; replace_text(dry_run=True) so edits are previewed before they're committed.
Who it's for: developers who want Claude to work directly across a real codebase or document tree — through Claude Desktop, Claude Code, or any MCP-compatible client — without babysitting what gets read.
- 🎯 Scoped by design — access is limited to directories you explicitly allow, passed as CLI arguments exactly like the official filesystem MCP server. Nothing outside that scope is reachable.
- ⚡ Preview & chunked reads — pull the first N lines or a specific byte-range chunk instead of an entire file, so large files don't blow the context window.
- 🔍 Multi-language code intelligence — AST-accurate function/class/import extraction for Python, regex-based for JavaScript, Go, and Rust.
- ✏️ Dry-run edits — preview a find-and-replace before committing it, so you see the diff before anything changes on disk.
- 🧭 Fast search, not full reads — search by filename, extension, or content (plain text or regex) with contextual snippets instead of whole-file dumps.
- 📦 Batch reads with size guards — read multiple related files in one call, capped so a batch can't quietly consume your whole budget.
- 🐳 Production Docker setup — non-root user, resource limits, a real process healthcheck (not a no-op).
- 🧪 Actually tested — path-safety, CLI-arg handling, and content search all have regression tests in
tests/.
Once installed, Claude Desktop renders a native config screen generated directly from manifest.json — pick allowed directories, and tools are auto-grouped into "Read-only" vs. "Write/destructive" based on each tool's annotations.
You: What's in my project, and does it have any TODOs left?
Claude uses: get_tree(path=".", max_depth=2)
search_content(query="TODO")
Result: A directory tree plus every TODO with file and line number —
without Claude reading a single full file.
| Technology | Purpose |
|---|---|
| Python 3.8+ | Core implementation — a single, dependency-light module |
MCP Python SDK (FastMCP) |
Tool registration, annotations, and the stdio transport Claude speaks |
Pydantic (via mcp) |
Tool annotation schema (ToolAnnotations) |
ast (stdlib) |
100%-accurate Python function/class/import extraction |
re (stdlib) |
Regex-based structure extraction for JS/Go/Rust, and regex search mode |
| Docker | Optional containerized deployment, non-root, healthchecked |
MCPB (manifest_version 0.3) |
Packaging format for Claude Desktop's Extensions / Connectors Directory |
| pytest | Regression tests for path safety, CLI config, and content search |
| OS | Linux, macOS, Windows |
| Python | 3.8 or newer |
| RAM | ~50MB base |
| Network | None — fully local, no outbound calls |
| Docker (optional) | 20.10+ with Compose 1.29+ |
# 1. Clone
git clone https://github.com/Mdskun/mcp-fs-agent.git
cd mcp-fs-agent
# 2. Install dependencies
pip install -r requirements.txt
# 3. Run — pass the directory Claude should access as an argument
python server3.py /path/to/your/projectsYou should see:
============================================================
🚀 MCP FILESYSTEM AGENT v3 (PRODUCTION-READY)
============================================================
📁 BASE DIRECTORIES (1):
1. /path/to/your/projects
============================================================
Add to your claude_desktop_config.json:
{
"mcpServers": {
"filesystem-agent": {
"command": "python",
"args": ["/path/to/mcp-fs-agent/server3.py", "/path/to/your/projects"]
}
}
}Restart Claude Desktop. Add more allowed directories by listing more paths in args — one server, multiple scoped roots.
docker-compose up -d
docker-compose logs -f # watch it start
docker-compose down # stop itLinux (systemd)
# /etc/systemd/system/mcp-fs-agent.service
[Unit]
Description=MCP Filesystem Agent
After=network.target
[Service]
Type=simple
User=your-username
Environment="MCP_BASE_DIR=/home/your-username/projects"
ExecStart=/home/your-username/mcp-fs-agent/venv/bin/python /home/your-username/mcp-fs-agent/server3.py
Restart=always
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now mcp-fs-agentWindows (nssm)
nssm install mcp-fs-agent "C:\path\to\venv\Scripts\python.exe" "C:\path\to\server3.py" "C:\Users\YourName\Projects"
nssm start mcp-fs-agentTroubleshooting
| Symptom | Fix |
|---|---|
No module named 'mcp' |
pip install -r requirements.txt |
Access denied: Path outside allowed directories |
Double-check the path passed as a CLI arg or MCP_BASE_DIR |
| Claude doesn't see the server | Fully quit and reopen Claude Desktop (a reload isn't enough) |
| Out of memory on a huge file | Use read_file_chunked() instead of read_file() |
python server3.py /path/to/projects
python server3.py /path/to/projects /path/to/documents /data/external # multiple roots| Variable | Default | Description |
|---|---|---|
MCP_BASE_DIR |
~/Data/Repos |
Single allowed directory |
MCP_BASE_DIRS |
(not set) | Comma-separated list of allowed directories |
PYTHONUNBUFFERED |
1 |
Unbuffered stderr output (recommended) |
Priority order: CLI args → MCP_BASE_DIRS → MCP_BASE_DIR → default.
Edit near the top of server3.py:
MAX_FILE_SIZE_KB = 2000 # single-file read/write cap (2MB)
MAX_RESULTS = 50 # max search results returned
DEFAULT_CHUNK_SIZE_KB = 50 # chunk size for read_file_chunked()
TOTAL_BATCH_SIZE_KB = 5000 # cap for batch_read_files()
MAX_LINES_TO_SEARCH = 10000 # cap for search_content()The repo ships manifest.json (MCPB spec 0.3) so it can be packaged as a .mcpb bundle and installed as a Claude Desktop extension — this is what renders the native "Allowed Directories" config screen.
# 1. Bundle the mcp dependency using the *exact* interpreter that will run it
/usr/bin/python3 -m pip install "mcp>=1.9,<2" --target=server/lib
# 2. Install the MCPB CLI
npm install -g @anthropic-ai/mcpb
# 3. Validate, then pack
mcpb validate manifest.json
mcpb pack .Interpreter mismatch is the #1 failure mode.
pydantic_coreships a compiled binary — if youpip install --target=server/libfrom a venv or conda environment that isn't the exact Python Claude Desktop launches (usually/usr/bin/python3), you'll getModuleNotFoundError: No module named 'pydantic_core._pydantic_core'at runtime. Always install with the target interpreter itself (/usr/bin/python3 -m pip install ..., not a barepip install ...).
Install the resulting .mcpb in Claude Desktop, test it against a disposable directory first, then submit via the Desktop Extension form (a separate path from the Connectors Directory portal, which is for remote HTTPS servers only).
User flow:
- You point the server at one or more directories (CLI args, env var, or the Desktop Extension's directory picker).
- Claude calls a tool — say,
search_content(query="TODO"). - Every path is resolved and checked against the allowed directories before any file touches disk.
- A compact, structured
ToolResponsecomes back — not a raw file dump.
Internally:
Claude ──▶ FastMCP tool call ──▶ safe_path() validation ──▶ file operation ──▶ ToolResponse
│
└─ segment-aware check via Path.relative_to()
(rejects sibling-directory & ../ traversal)
There's no framework pattern here beyond "one function per tool" — it's a single, flat module by design, prioritizing readability over abstraction for a project this size.
mcp-fs-agent/
├── server3.py # The entire server — all 22 tools, one file
├── manifest.json # MCPB packaging manifest (Desktop Extension config)
├── requirements.txt # Runtime dependency (mcp SDK)
├── .mcpbignore # Excludes venv/tests/docs from the packed bundle
├── Dockerfile # Non-root, healthchecked container build
├── docker-compose.yml # One-command Docker deployment
├── PRIVACY.md # Data-handling policy (required for submission)
├── SECURITY.md # Security features, known limitations, disclosure process
├── CHANGELOG.md # Version history, including real fixes (not just features)
├── CONTRIBUTING.md # Dev setup, tool template, PR process
└── tests/
├── test_safe_path.py # Path-traversal regression tests
├── test_cli_args.py # CLI-arg config priority tests
└── test_search_content.py # Content-search matching regression tests
- 📝 CHANGELOG.md — every version, including the real bugs that got fixed (a string-prefix path check, a broken match object in search) — not just a feature list.
- 🔒 SECURITY.md — security model, Docker hardening, and how to report a vulnerability.
- 🔐 PRIVACY.md — what data this touches (nothing leaves your machine).
- 🤝 CONTRIBUTING.md — dev setup, the required tool-annotation pattern, commit conventions.
- Path validation is segment-aware (
Path.relative_to()), not a naive string-prefix check — sibling directories that share a name prefix with an allowed folder can't be reached. - Zero network calls. No telemetry, no analytics, nothing sent anywhere. See PRIVACY.md for the full policy.
- Every tool is annotated (
readOnlyHint/destructiveHint) so Claude Desktop can correctly group and gate write/destructive operations from read-only ones.
Full details in SECURITY.md.
Contributions are welcome — especially test coverage for the write/edit tools, which is the biggest known gap right now.
git checkout -b feature/your-feature-name
# make changes, add tests
pytest tests/ -vSee CONTRIBUTING.md for the full dev setup, the required tool-annotation pattern for new tools, and PR conventions.
Released under the MIT License — use it, modify it, ship it.
Manthan (@Mdskun)
If this saved you a context window or two, a ⭐ on the repo is the easiest way to say thanks.
