MCP Filesystem Agent v3
by Mdskun
README.md
<div align="center">
# ๐๏ธ MCP Filesystem Agent
### Token-efficient filesystem access for Claude โ read, write, search, and analyze code without burning your context window
<p align="center">
<img src="FileAgent.png" alt="MCP Filesystem Agent" width="140" />
</p>
[](LICENCE)
[](CHANGELOG.md)
[](https://www.python.org/downloads/)
[](manifest.json)
[](https://github.com/Mdskun/mcp-fs-agent/stargazers)
**[Quick Start](#-quick-start) ยท [Features](#-features) ยท [Configuration](#-configuration) ยท [Tech Stack](#-tech-stack) ยท [Contributing](#-contributing)**
</div>
---
## ๐ Table of Contents
- [Overview](#-overview)
- [Features](#-features)
- [Demo](#-demo)
- [Tech Stack](#-tech-stack)
- [Requirements](#-requirements)
- [Quick Start](#-quick-start)
- [Configuration](#-configuration)
- [Packaging as a Desktop Extension](#-packaging-as-a-desktop-extension)
- [How It Works](#-how-it-works)
- [Project Structure](#-project-structure)
- [Documentation](#-documentation)
- [Security & Privacy](#-security--privacy)
- [Contributing](#-contributing)
- [License](#-license)
- [Author](#-author)
---
## ๐ญ Overview
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](https://modelcontextprotocol.io) 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.
---
## โจ Features
- ๐ฏ **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/`.
---
## ๐ผ๏ธ Demo
<p align="center">
<em>Once installed, Claude Desktop renders a native config screen generated directly from <code>manifest.json</code> โ pick allowed directories, and tools are auto-grouped into "Read-only" vs. "Write/destructive" based on each tool's annotations.</em>
</p>
```
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.
```
---
## ๐งฑ Tech Stack
| Technology | Purpose |
|---|---|
| **Python 3.8+** | Core implementation โ a single, dependency-light module |
| **[MCP Python SDK](https://github.com/modelcontextprotocol/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 |
---
## ๐ Requirements
| | |
|---|---|
| **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+ |
---
## ๐ Quick Start
```bash
# 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/projects
```
You should see:
```
============================================================
๐ MCP FILESYSTEM AGENT v3 (PRODUCTION-READY)
============================================================
๐ BASE DIRECTORIES (1):
1. /path/to/your/projects
============================================================
```
### Connect it to Claude Desktop
Add to your `claude_desktop_config.json`:
```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.
### Run it in Docker instead
```bash
docker-compose up -d
docker-compose logs -f # watch it start
docker-compose down # stop it
```
### Prefer a system service?
<details>
<summary><strong>Linux (systemd)</strong></summary>
```ini
# /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.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now mcp-fs-agent
```
</details>
<details>
<summary><strong>Windows (nssm)</strong></summary>
```cmd
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-agent
```
</details>
<details>
<summary><strong>Troubleshooting</strong></summary>
| 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()` |
</details>
---
## โ๏ธ Configuration
### Simplest: command-line arguments (recommended)
```bash
python server3.py /path/to/projects
python server3.py /path/to/projects /path/to/documents /data/external # multiple roots
```
### Alternative: environment variables
| 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.**
### Tunable limits
Edit near the top of `server3.py`:
```python
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()
```
---
## ๐ฆ Packaging as a Desktop Extension
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.
```bash
# 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_core` ships a compiled binary โ if you `pip install --target=server/lib` from a venv or conda environment that isn't the exact Python Claude Desktop launches (usually `/usr/bin/python3`), you'll get `ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'` at runtime. Always install with the target interpreter itself (`/usr/bin/python3 -m pip install ...`, not a bare `pip 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).
---
## ๐ง How It Works
**User flow:**
1. You point the server at one or more directories (CLI args, env var, or the Desktop Extension's directory picker).
2. Claude calls a tool โ say, `search_content(query="TODO")`.
3. Every path is resolved and checked against the allowed directories before any file touches disk.
4. A compact, structured `ToolResponse` comes 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.
---
## ๐ Project Structure
```
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
```
---
## ๐ Documentation
- ๐ **[CHANGELOG.md](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.md)** โ security model, Docker hardening, and how to report a vulnerability.
- ๐ **[PRIVACY.md](PRIVACY.md)** โ what data this touches (nothing leaves your machine).
- ๐ค **[CONTRIBUTING.md](CONTRIBUTING.md)** โ dev setup, the required tool-annotation pattern, commit conventions.
---
## ๐ Security & Privacy
- **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](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](SECURITY.md).
---
## ๐ค Contributing
Contributions are welcome โ especially test coverage for the write/edit tools, which is the biggest known gap right now.
```bash
git checkout -b feature/your-feature-name
# make changes, add tests
pytest tests/ -v
```
See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the full dev setup, the required tool-annotation pattern for new tools, and PR conventions.
---
## ๐ License
Released under the **[MIT License](LICENCE)** โ use it, modify it, ship it.
---
## ๐ค Author
**Manthan** ([@Mdskun](https://github.com/Mdskun))
If this saved you a context window or two, a โญ on the repo is the easiest way to say thanks.
<div align="center">
**[โฌ Back to top](#-mcp-filesystem-agent)**
</div>
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues