Skip to main content
Glama
Mdskun

MCP Filesystem Agent v3

by Mdskun

πŸ—‚οΈ MCP Filesystem Agent

Token-efficient filesystem access for Claude β€” read, write, search, and analyze code without burning your context window

License: MIT Version Python 3.8+ MCPB GitHub stars

Quick Start Β· Features Β· Configuration Β· Tech Stack Β· Contributing


πŸ“‘ Table of Contents


Related MCP server: vulcan-file-ops

πŸ”­ 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 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

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 (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

# 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:

{
  "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

docker-compose up -d
docker-compose logs -f     # watch it start
docker-compose down        # stop it

Prefer a system service?

# /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
sudo systemctl daemon-reload
sudo systemctl enable --now mcp-fs-agent
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

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()


βš™οΈ Configuration

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:

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.

# 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 β€” 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.


πŸ”’ 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 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.


🀝 Contributing

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/ -v

See CONTRIBUTING.md for the full dev setup, the required tool-annotation pattern for new tools, and PR conventions.


πŸ“„ License

Released under the MIT License β€” use it, modify it, ship it.


πŸ‘€ Author

Manthan (@Mdskun)

If this saved you a context window or two, a ⭐ on the repo is the easiest way to say thanks.

⬆ Back to top

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    An MCP server that implements Claude Code-like functionality, allowing the AI to analyze codebases, modify files, execute commands, and manage projects through direct file system interactions.
    15
    304
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that delegates filesystem operations to a specialized React agent, reducing context usage and improving accuracy for AI applications like Claude Code.
    5 npm
    3
    MIT