Surgicalfs Mcpserver
High-performance, context-efficient filesystem MCP server built in Rust
Ask AI about Surgicalfs Mcpserver
Powered by Claude Β· Grounded in docs
I know everything about Surgicalfs Mcpserver. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
SurgicalFS MCP Server
High-performance, context-efficient filesystem MCP server built in Rust. Designed as a drop-in replacement for the default @modelcontextprotocol/server-filesystem β with surgical read/write operations, structured file format support, and aggressive context window optimization.
Version: 0.4.1 Β· 47 tools Β· Rust + rmcp SDK Β· Windows-first, cross-platform compatible
Works with any MCP-compatible client: Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, Zed, ChatGPT (via remote MCP), Gemini, and more.
Why SurgicalFS?
The default MCP filesystem server has several limitations that become painful in real-world usage:
- Context pollution β
read_filedumps entire file contents into the conversation, burning tokens on irrelevant lines - No partial editing β every edit requires reading the full file, modifying it, and writing it back
- Slow cold-start β Node.js process spins up on every invocation
- Security gaps β known path traversal CVEs (CVE-2025-53109, CVE-2025-53110) in the reference implementation
- No structured formats β no native support for JSON queries, CSV filtering, XLSX/PDF/DOCX extraction
SurgicalFS addresses all of these with a single compiled binary that starts instantly, enforces a path allowlist, and provides tools designed to minimize context window usage at every level.
Design Philosophy: Context Economy
Every tool in SurgicalFS is designed around a single principle: never put bytes into the context window that don't need to be there.
- Read tools support head/tail/line-range access β never load a full file when you need 10 lines
- Mutation tools return compact summaries (line numbers, counts), never the modified file content
- Search tools offer tiered verbosity:
fullβlinesβcount, from richest to cheapest - A server-side response budget hard-caps every response before it enters the conversation
- Write strategies guide the model toward chunked writes, staging files, and batch edits to avoid repeating content
- Tool descriptions embed context hygiene directives that steer LLM behavior at the protocol level
How It Compares
| Server | Tools | Est. definition tokens | Partial reads | Structured formats | Response budget |
|---|---|---|---|---|---|
| Official filesystem | 14 | ~1,500 | No | No | No |
| Desktop Commander | ~25 | ~8,000 | No (full reads) | XLSX/PDF/DOCX | No |
| safurrier/mcp-filesystem | ~20 | ~4,000 | Yes | No | No |
| SurgicalFS (all tools) | 47 | ~14,000 | Yes | JSON/CSV/XLSX/PDF/DOCX | Yes |
| SurgicalFS (core only) | ~17 | ~5,000 | Yes | No | Yes |
SurgicalFS costs more upfront in tool definitions, but recoups it on the first operation. A single read_file call on a 200-line file through the official server dumps ~800 tokens; SurgicalFS's file_head with 20 lines returns ~100 tokens. Over a typical coding session, the response-side savings far exceed the definition overhead.
Tip: If tool definition overhead is a concern, disable unnecessary categories via config. See Tool Categories & Config-Driven Profiles.
Installation
Build from source
cargo build --release
Binary location depends on your toolchain. With the GNU target (recommended on Windows):
target/x86_64-pc-windows-gnu/release/surgicalfs-mcp.exe
On Linux/macOS with the default target:
target/release/surgicalfs-mcp
Configure for your MCP client
SurgicalFS uses stdio transport (JSON-RPC over stdin/stdout), which is the standard for local MCP servers. The configuration pattern is the same across clients: point the client at the binary and optionally specify a config file.
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"surgicalfs": {
"command": "/path/to/surgicalfs-mcp",
"args": []
}
}
}
Config file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Claude Code
claude mcp add surgicalfs -- /path/to/surgicalfs-mcp
Cursor
Add to Cursor Settings β MCP, or in .cursor/mcp.json:
{
"mcpServers": {
"surgicalfs": {
"command": "/path/to/surgicalfs-mcp",
"args": []
}
}
}
VS Code (Copilot)
Add to .vscode/mcp.json (per-workspace) or user mcp.json:
{
"servers": {
"surgicalfs": {
"command": "/path/to/surgicalfs-mcp",
"args": []
}
}
}
Windsurf
Add to ~/.windsurf/mcp.json or the project-level equivalent:
{
"mcpServers": {
"surgicalfs": {
"command": "/path/to/surgicalfs-mcp",
"args": []
}
}
}
Zed
Add to Zed's settings under context_servers:
{
"context_servers": {
"surgicalfs": {
"command": {
"path": "/path/to/surgicalfs-mcp",
"args": []
}
}
}
}
Remote access (ChatGPT, Gemini, claude.ai web/mobile, and other HTTP clients)
SurgicalFS uses stdio transport natively. To expose it over HTTP for web-based clients, use supergateway to bridge stdio to streamable HTTP, then put it behind a reverse tunnel (Cloudflare Tunnel, ngrok, etc.):
npx supergateway --stdio "/path/to/surgicalfs-mcp" --port 8080 --outputTransport streamableHttp
Then point your tunnel at localhost:8080 and register the public URL in your client's MCP integration settings.
Note: AI providers make outbound connections to your MCP endpoint β
localhostURLs won't work from hosted clients. A tunnel or public-facing server is required.
Security: MCP over HTTP has no built-in authentication. Anyone who discovers your tunnel URL can call any tool and read/write files within your allowed directories. Secure your tunnel with IP allowlisting (e.g., Cloudflare WAF rules restricting to your AI provider's IP ranges), VPN, or equivalent access controls before exposing to the internet. The
--read-onlyflag provides an additional safety layer for remote deployments.
Configuration
Open configure.html in your browser for an interactive config generator β toggle tool categories, see live token cost estimates, and copy the generated TOML and client registration snippets.
SurgicalFS looks for surgicalfs.toml in this order:
- Next to the executable
- Platform config directory:
- Windows:
%APPDATA%\surgicalfs-mcp\config.toml - macOS/Linux:
~/.config/surgicalfs-mcp/config.toml
- Windows:
- Explicit path:
surgicalfs-mcp --config /path/to/surgicalfs.toml
Full configuration reference
[security]
# REQUIRED: directories the server is allowed to access.
# All path operations are validated against this allowlist.
# Symlinks that resolve outside these directories are blocked.
allowed_directories = ["/home/yourname/projects"]
follow_symlinks = false # default: false
max_file_size = 5242880 # bytes, default: 5MB
[search]
ripgrep_path = "auto" # "auto" (PATH β beside exe β native fallback), or explicit path
max_results = 100 # default cap for search results
default_context_lines = 2 # lines of context around matches
[defaults]
head_lines = 50 # default for file_head
tail_lines = 50 # default for file_tail
max_read_lines = 500 # cap for file_read_lines range
encoding = "auto" # "auto", "utf-8", "windows-1252"
[response_budget]
max_response_lines = 200 # hard cap on response line count
max_response_bytes = 32768 # hard cap on response byte size (32KB)
truncation_mode = "smart" # "smart" (break at newline) or "hard" (exact byte cut)
Tools Reference
SurgicalFS provides 47 tools across 11 categories: surgical operations purpose-built for context efficiency, plus a backwards-compatible layer that mirrors the default MCP filesystem server.
Inspect (4 tools)
| Tool | Description |
|---|---|
file_info | File metadata (size, line count, encoding, timestamps) without reading content |
file_head | First N lines (default: 50) with truncation indicator |
file_tail | Last N lines (default: 50) with start line number |
file_read_lines | Specific line range (1-indexed, inclusive) |
Search (3 tools)
| Tool | Description |
|---|---|
file_search | Multi-file/directory pattern search via ripgrep. Supports return_mode: full (lines + context), lines (file:line pairs only, ~80% fewer tokens), count (matches per file, ~95% fewer tokens) |
file_grep | Single-file grep returning line numbers only by default. include_content=true adds matching text. Most token-efficient way to locate patterns in a known file |
file_search_replace_preview | Dry-run find-and-replace showing before/after diffs without modifying the file |
Mutate (5 tools)
| Tool | Description |
|---|---|
file_replace | In-place find-and-replace (literal or regex). Returns change count + line numbers, never file content. Supports multi-line patterns with \r\n normalization |
file_insert | Insert text at a line number, or before/after a pattern match. Accepts anchor as object or JSON string |
file_append | Append text to end of file |
file_patch_lines | Replace a line range with new content |
file_batch_edit | Multiple edits in one atomic operation. ~90% less context than individual calls for 3+ edits |
JSON (2 tools)
| Tool | Description |
|---|---|
json_query | JSONPath queries (RFC 9535) returning matched nodes only |
json_mutate | Modify JSON at JSONPath locations (set, delete, insert, append) |
CSV (4 tools)
| Tool | Description |
|---|---|
csv_info | Column names, row count, detected delimiter |
csv_read | Read specific rows and/or columns |
csv_query | Filter rows by column value (eq, neq, contains, gt, lt, gte, lte, regex) |
csv_write | Create new CSV or append rows to existing |
Documents (3 tools)
| Tool | Description |
|---|---|
pdf_info | Page count and file size without extracting text |
pdf_extract | Extract text by page range, one string per page |
docx_extract | Extract text from .docx with offset/max_chars pagination |
Spreadsheets (3 tools)
| Tool | Description |
|---|---|
xlsx_info | Sheet names and dimensions for .xlsx, .xls, .ods |
xlsx_read | Read cells by sheet and range (Excel notation, e.g., B2:D10) |
xlsx_query | Search for values across sheets without loading full data |
File Management (6 tools)
| Tool | Description |
|---|---|
file_write | Create/overwrite a file (recommended for <50 lines) |
file_write_chunked | Verified chunked writes for large files. Sessions persist to disk for stateless transports |
file_write_stream | Atomic copy/move of a staging file to final destination with optional SHA-256 verification |
file_copy | Disk-to-disk copy β content never enters the conversation |
file_delete | Delete a file |
file_move | Move or rename a file |
Directory (2 tools)
| Tool | Description |
|---|---|
directory_list | List contents with metadata, glob filtering, depth control, sorting |
directory_tree | ASCII tree visualization with optional file sizes |
Utility (1 tool)
| Tool | Description |
|---|---|
file_checksum | SHA-256, MD5, or BLAKE3 checksum without reading file into context |
Backwards-Compatible Layer (14 tools)
Drop-in replacements for every tool in the default @modelcontextprotocol/server-filesystem, so existing workflows and prompts continue to work unchanged:
read_file, read_text_file, read_media_file, read_multiple_files, write_file, edit_file, create_directory, list_directory, list_directory_with_sizes, directory_tree_compat, move_file, search_files, get_file_info, list_allowed_directories
Tool descriptions in the compat layer steer the model toward the surgical alternatives (e.g., read_file's description suggests file_read_lines or file_head for large files).
Tool Categories & Config-Driven Profiles
MCP tool definitions consume context window tokens on every interaction β typically 250β500 tokens per tool. With 47 tools, SurgicalFS costs roughly 14,000 tokens of definition overhead. While this is modest compared to servers like GitHub MCP (~55,000 tokens for 93 tools), it can matter in token-constrained environments.
Some clients implement deferred tool loading (e.g., claude.ai's tool search), which avoids upfront injection. But most clients β including Cursor, VS Code, and ChatGPT β load all definitions eagerly.
Note: Cursor enforces a hard limit of 40 tools. SurgicalFS's full catalog of 47 exceeds this. Use a profile to stay within client limits.
Profiles
Configure which tool categories are registered via surgicalfs.toml:
[tools]
# Only register these categories in tools/list
enable = ["inspect", "search", "mutate", "manage", "directory", "utility"]
# Omitted categories won't appear in the tool catalog at all.
# Categories: inspect, search, mutate, json, csv, document, spreadsheet,
# manage, directory, utility, compat
| Profile | Categories | Tools | Est. tokens |
|---|---|---|---|
| Full (default) | All 11 | 47 | ~14,000 |
| Core | inspect, search, mutate, manage, directory, utility | ~17 | ~5,000 |
| Core + formats | Core + json, csv, document, spreadsheet | ~29 | ~9,000 |
| Compat only | compat | 14 | ~4,000 |
This gives you granular control over the cost/capability tradeoff. Users who don't need XLSX parsing, the compat layer, or CSV operations simply don't pay for them.
Token Efficiency Guide
SurgicalFS provides multiple verbosity tiers for search operations, letting you trade detail for token savings:
file_search return modes
return_mode | Response shape | Token cost |
|---|---|---|
full (default) | Matching lines with surrounding context | High |
lines | {file, line} pairs only | ~80% less |
count | Match count per file | ~95% less |
file_grep modes
| Mode | Response shape | Token cost |
|---|---|---|
| Default | Line numbers only: [5, 12, 89] | Minimal |
include_content=true | {line, content} pairs | Low |
search_files limiting
Set max_results to cap glob results (default can return up to 200 paths).
Write strategy selection
| Scenario | Recommended tool | Why |
|---|---|---|
| New file, <50 lines | file_write | Single call, simple |
| New file, 50+ lines | file_write_chunked | Verified chunks, no re-output |
| Assembled from sources | file_append β file_write_stream | Build staging file, then promote |
| Edit 1β2 locations | file_replace or file_insert | Returns summary, not content |
| Edit 3+ locations | file_batch_edit | ~90% less context than individual calls |
| Duplicate existing file | file_copy | Zero context cost |
Architecture
src/
βββ main.rs # CLI parsing, config loading, server startup
βββ config.rs # TOML config types and defaults
βββ server.rs # MCP ServerHandler with #[tool_router] + #[tool_handler]
βββ pathguard.rs # Security: path allowlist, symlink blocking, size guards
βββ encoding.rs # BOM detection, UTF-8/Windows-1252 fallback
βββ search_backend.rs # ripgrep (preferred) / native Rust (fallback) search
βββ response_budget.rs # Hard response truncation (char-boundary safe)
βββ errors.rs # Structured errors with suggestions
βββ tools/
βββ inspect.rs # file_info, file_head, file_tail, file_read_lines
βββ search.rs # file_search, file_grep, file_search_replace_preview
βββ mutate.rs # file_replace, file_insert, file_append, file_patch_lines, file_batch_edit
βββ json_ops.rs # json_query, json_mutate
βββ csv_ops.rs # csv_info, csv_read, csv_query, csv_write
βββ document.rs # pdf_info, pdf_extract, docx_extract
βββ spreadsheet.rs # xlsx_info, xlsx_read, xlsx_query
βββ manage.rs # file_write, file_write_chunked, file_write_stream, file_copy, file_delete, file_move
βββ directory.rs # directory_list, directory_tree
βββ utility.rs # file_checksum
βββ compat.rs # 14 backwards-compatible tools matching default MCP filesystem server
Security Model
- Path allowlist β every operation validates paths against
allowed_directoriesbefore any I/O - Symlink blocking β symlinks resolving outside allowed directories are rejected (configurable)
- File size guard β configurable
max_file_sizeprevents accidental reads of huge files - Case-insensitive paths β Windows drive letters and paths handled correctly via
dunce - No
unsafeblocks β zero unsafe Rust in the entire codebase - Zero
cargo auditadvisories β no known dependency vulnerabilities
Search Backend
SurgicalFS auto-detects ripgrep for maximum search performance:
- Checks
PATHforrg - Checks next to the SurgicalFS binary
- Falls back to a native Rust search backend (regex + walkdir)
The fallback is fully functional but slower on large directory trees. Bundling rg (or rg.exe) next to the SurgicalFS binary is recommended for best performance.
Response Budget
Every tool response passes through a server-side budget filter before being sent via MCP:
max_response_linesβ hard line count capmax_response_bytesβ hard byte size captruncation_modeβsmart(break at nearest newline) orhard(exact byte cut, char-boundary safe)
This ensures that even if a tool produces a large result, the context window impact is bounded. No other filesystem MCP server provides this.
Development
cargo build # Debug build
cargo build --release # Optimized, stripped, LTO-enabled release build
cargo test # Run all tests (~112 tests)
cargo clippy # Lint (zero warnings policy)
cargo fmt # Format
cargo audit # Dependency vulnerability scan (zero advisories)
Build profile
The release profile is tuned for minimal binary size and maximum performance:
[profile.release]
opt-level = 3
lto = true
strip = true
codegen-units = 1
Key Dependencies
| Crate | Purpose |
|---|---|
rmcp | Rust MCP SDK (server mode, stdio transport) |
serde_json_path | JSONPath RFC 9535 queries |
calamine | XLSX/XLS/ODS spreadsheet reading |
pdf-extract | PDF text extraction |
dotext | DOCX text extraction |
csv | CSV parsing and writing |
regex | Pattern matching |
walkdir | Directory traversal |
dunce | Windows-safe path canonicalization |
sha2, md-5, blake3 | Checksums |
encoding_rs | Encoding detection and conversion |
clap | CLI argument parsing |
Version History
| Version | Changes |
|---|---|
| v0.4.1 | Security audit fixes: integer overflow in file_grep pagination (switched to saturating_add). Config validation for empty/invalid tool category names. Updated tool descriptions for expected_content. Edge case tests for CRLF content verification and overflow saturation. |
| v0.4.0 | Config-driven tool categories ([tools] enable). .gitignore support via ignore crate. --read-only CLI flag. Search pagination (offset param). Content verification (expected_content on file_patch_lines and file_insert). |
| v0.3.4 | Fixed file_replace silently failing on multi-line find patterns (now uses whole-text matching with \r\n normalization). Fixed file_insert anchor parsing from web-based MCP clients (auto-parses JSON string anchors). Added file_grep single-file search tool. Added return_mode (full/lines/count) to file_search. Added max_results to search_files. |
| v0.3.3 | Fixed chunked write session timeout: sessions now persist to temp directory for stateless transports (e.g., supergateway streamableHttp). |
| v0.3.2 | Fixed PDF page extraction: replaced extract_text() + form-feed splitting with per-page extraction. |
| v0.3.1 | Code audit: removed dead code, fixed char-boundary panics in docx_extract and read_text_file, fixed file_insert offset bug with occurrence=all. |
| v0.3.0 | Added file_copy for disk-to-disk copy without content round-tripping. |
| v0.2.0 | Fixed tools/list returning empty array (added #[tool_handler] macro). Replaced broken PowerShell search fallback with native Rust backend. Fixed response budget truncation panic on multi-byte UTF-8. |
| v0.1.0 | Initial release. All tools implemented and tested. |
Roadmap
- MCP Roots protocol support β dynamic directory updates from clients without server restart
- File diff tool β unified diff between two files for code review workflows
- ZIP/archive support β create and extract archives
License
MIT License. See LICENSE for details.
Acknowledgements
Built with the Rust MCP SDK (rmcp). SurgicalFS implements the Model Context Protocol, an open standard under the Linux Foundation for connecting AI assistants to external tools and data sources.
The content verification feature (expected_content on file_patch_lines and file_insert) is inspired by safurrier/mcp-filesystem by Alex Furrier (MIT licensed).
