Back to blog

Engineering · Jul 14, 2026

MCP Spotlight: Filesystem MCP Server — Anthropic's Reference Implementation for Sandboxed, Allowed-Directory-Scoped File Access

The official Filesystem MCP Server by Anthropic — ~14 focused tools covering read, write, edit, search, directory, metadata. Explicit allowed-directories allow-list at startup (deny-by-default), Roots-aware dynamic updates, image support. MIT-licensed, available via NPX or Docker. The local-file-access default for AI agents in 2026.

MCP ServerFilesystemAnthropicSandboxAllowed DirectoriesAI Agents

MCP Spotlight: Filesystem MCP Server — Anthropic's Reference Implementation for Sandboxed, Allowed-Directory-Scoped File Access

Server: @modelcontextprotocol/server-filesystem by Anthropic License: MIT · Tools: ~14 (read, write, edit, search, directory, metadata) · Transport: stdio or Docker Security: Explicit allowed-directories allow-list · read/write/edit/move/delete modes · Roots-aware dynamic updates GitHub: github.com/modelcontextprotocol/servers/tree/main/src/filesystem NPM: @modelcontextprotocol/server-filesystem Docker: mcp/filesystem · MCP Tracker: glama.ai/mcp/servers/modelcontextprotocol/filesystem

Every agent that does real work eventually needs the filesystem. The "give the agent unrestricted filesystem access" approach is a security incident waiting to happen — the agent reads ~/.ssh/id_rsa, writes to /etc/passwd, deletes the user's home directory. The "give the agent nothing" approach blocks every workflow that benefits from local file processing — code review, document editing, log analysis, project bootstrapping. The naive "wrap fs.readFile / fs.writeFile" approach gives the agent full filesystem access through a thin wrapper.

The official Filesystem MCP Server by Anthropic is the bridge that resolves this. ~14 tools covering the file operations an agent actually needs — read, write, edit, search, directory navigation, metadata — all gated behind an explicit allowed-directories allow-list. The agent can ONLY access directories the operator explicitly authorized. Out-of-bounds paths are blocked at the server level. MIT-licensed, official Anthropic-maintained, available via NPX or Docker.

This is the local-file-access default for AI agents in 2026. Small surface, hard sandbox boundary, ubiquitous use.

The Architecture: Allowed-Directories Sandboxing

The Filesystem MCP Server's defining design choice: the server refuses any access to a directory not in its allowed list. The configuration is explicit:

# Option A: NPX with explicit allowed directories
npx -y @modelcontextprotocol/server-filesystem /home/user/projects /tmp/scratch

# Option B: Docker with explicit allowed directories
docker run -i --rm \
  -v /home/user/projects:/projects:rw \
  -v /tmp/scratch:/scratch:rw \
  mcp/filesystem /projects /scratch

The directories passed at startup are the complete set the agent can access. There's no "current working directory" trick, no relative path escape, no symlink attack — the server validates every operation against the allow-list before executing.

If the agent tries read_file("/etc/passwd"), the server returns an error: path not in allowed directories. If the agent tries read_file("/home/user/projects/../../../etc/passwd"), the server resolves the path and rejects it. No path traversal, no escape, no exceptions.

The allow-list is the security boundary. Set it correctly, and the agent can only touch what you want it to touch.

The Roots Pattern: Dynamic Allowed Directories

For MCP clients that support the Roots protocol extension, the allowed directories can be updated dynamically:

Client → Server: "I now allow these directories: /projects/repo-a, /projects/repo-b"
Server: "Updated. Allowed directories: repo-a, repo-b. Cache invalidated."

The agent's working set changes as the user navigates between projects. The Roots mechanism is the dynamic scope mechanism — the operator grants per-project access, the agent operates within it, the operator moves to the next project.

This is the right pattern for IDE-integrated agents (Cursor, Windsurf, VS Code) where the user is constantly switching contexts. The filesystem scope matches the user's current focus.

The Tool Surface: ~14 Tools

The MCP surface covers the file operations an agent actually uses:

Read

ToolWhat It Does
read_fileRead a file (full content)
read_text_fileRead with explicit UTF-8 encoding
read_image_fileRead an image file (returns base64 + mime)
read_multiple_filesBatch read (efficient for multi-file context)

Write

ToolWhat It Does
write_fileWrite a file (overwrites if exists)
edit_fileSurgical edit (find-and-replace with uniqueness check)
create_directoryCreate a directory

Search

ToolWhat It Does
search_filesFind files matching a glob pattern
search_codeSearch file contents with regex
list_directoryList a directory's contents
list_allowed_directoriesShow the current allow-list (transparency)

Metadata

ToolWhat It Does
get_file_infoGet size, mtime, type, permissions
move_fileMove/rename a file
list_directory_with_sizesList with file sizes

The tools are well-named, well-scoped, and map directly to filesystem operations. The agent doesn't have to guess which library function to call.

The Read Patterns: How Agents Use the Filesystem

Single file read

read_file(path="/projects/repo/src/index.ts")
  → Returns the file content

Batch read for context

read_multiple_files(paths=[
  "/projects/repo/src/index.ts",
  "/projects/repo/src/config.ts",
  "/projects/repo/src/types.ts"
])
  → Returns the file contents in one call

For agents that need multi-file context (e.g., understanding a module), batch read is the efficient pattern — one round-trip, multiple files.

Search across files

search_code(
  path="/projects/repo",
  pattern="TODO|FIXME|XXX",
  file_pattern="*.{ts,js,tsx,jsx}"
)
  → Returns matching files with line numbers and context

The search returns structured results — file paths, line numbers, matched content. The agent can reason about where to focus.

Tree walking

list_directory(path="/projects/repo")
  → Returns:
    [
      {"name": "src", "type": "directory"},
      {"name": "tests", "type": "directory"},
      {"name": "package.json", "type": "file"},
      {"name": "README.md", "type": "file"}
    ]

list_directory(path="/projects/repo/src")
  → Returns the next level down

The agent builds the project's file tree iteratively.

The Write Patterns: Safe Mutations

Direct write (new file or full overwrite)

write_file(
  path="/projects/repo/src/utils.ts",
  content="// ... full file content ..."
)
  → Writes the file

For new files or full rewrites, write_file is the right primitive. The agent composes the full content and writes it.

Surgical edit (find and replace)

edit_file(
  path="/projects/repo/src/config.ts",
  edits=[{
    "oldText": "const PORT = 3000;",
    "newText": "const PORT = process.env.PORT || 3000;"
  }]
)
  → Surgically replaces the matched text

For targeted edits (refactor a constant, fix a typo, update an import), edit_file is the right primitive. The oldText must match exactly (whitespace included), the server enforces uniqueness, the edit is atomic.

Multi-edit in one call

edit_file(
  path="/projects/repo/src/api.ts",
  edits=[
    {"oldText": "import moment from 'moment';", "newText": "import { format } from 'date-fns';"},
    {"oldText": "moment(", "newText": "format(new Date(), "},
    {"oldText": "moment(", "newText": "format(new Date(), "}  // second occurrence
  ]
)

For multi-edit refactors, batch the edits in one call. The server validates uniqueness and applies atomically.

The Search Patterns: Discovery + Grep

The Filesystem server exposes two search tools — search_files (filename matching) and search_code (content matching):

Filename search

search_files(
  path="/projects/repo",
  pattern="*.test.ts"
)
  → Returns all TypeScript test files

Content search

search_code(
  path="/projects/repo/src",
  pattern="deprecated",
  context=3,
  file_pattern="*.ts",
  ignore_case=true
)
  → Returns matches with 3 lines of context

The agent can grep the codebase for patterns, identifiers, TODOs, deprecated APIs. The results are structured (file paths + line numbers + context), so the agent can follow up with read_file on specific matches.

The Image Support: Multimodal Files

The Filesystem MCP server handles image files too:

read_image_file(path="/projects/repo/docs/architecture.png")
  → Returns:
    {
      "type": "image",
      "mime_type": "image/png",
      "data": "<base64 encoded PNG data>"
    }

For agents that do visual reasoning (UI review, design feedback, image analysis), the image read primitive is invaluable. The base64 data flows into the agent's vision-capable context.

The Security Boundary: What Cannot Happen

The Filesystem MCP server's security model is deny-by-default:

  • /etc/passwd — blocked (not in allow-list)
  • ~/.ssh/id_rsa — blocked (not in allow-list)
  • ~/.aws/credentials — blocked (not in allow-list)
  • /var/log/ — blocked (not in allow-list)
  • Symlink traversal — resolved before allow-list check, then blocked
  • Path traversal../../etc/passwd resolved, blocked
  • Hidden files — only blocked if the parent directory isn't allowed (no special-casing)
  • Network paths — not supported (the filesystem is local-only)

The server's single job is enforcing the allow-list. Every operation goes through the check. There's no "developer override" or "sudo mode." If the path isn't allowed, the operation fails.

Facio Integration

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y", "@modelcontextprotocol/server-filesystem",
        "/home/user/projects",
        "/tmp/scratch",
        "/data/agent-workspace"
      ]
    }
  }
}

Or via Docker with explicit mounts:

{
  "mcpServers": {
    "filesystem": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/home/user/projects:/projects:rw",
        "-v", "/tmp/scratch:/scratch:rw",
        "mcp/filesystem", "/projects", "/scratch"
      ]
    }
  }
}

Facio's audit trail captures every Filesystem MCP call with the tool, the path, the operation, the result, and the diff (for edits). For a regulated team (SOC2, ISO 27001, financial compliance), this is the complete file-access record: "Agent at 14:32 UTC edited /projects/repo/src/config.ts, replaced 1 occurrence of 'const PORT = 3000;' with 'const PORT = process.env.PORT || 3000;'."

For HITL workflows, the Filesystem MCP server's destructive surface is meaningful — the agent can modify files:

ToolSeveritySuggested Gate
read_*, search_*, list_*, get_file_infoReadNone — autonomous
list_allowed_directoriesRead (transparency)None — autonomous
create_directoryWrite, contextualSoft confirm
write_file (existing file)Write, destructive in effectHard confirm if path matches sensitive patterns
write_file (new file)Write, contextualSoft confirm
edit_fileWrite, surgicalSoft confirm (review the diff)
move_fileWrite, destructive in effectHard confirm if destination exists
read_image_fileReadNone — autonomous

The write_file and move_file tools deserve special attention — overwriting an existing file or moving to an existing destination can lose data. Facio's parameter-aware policies can add extra gates:

  • path matches *.env, *.key, *.pem, id_rsa*hard confirm (secrets-adjacent files)
  • path matches /etc/*, /var/*, ~/.ssh/*hard confirm (system files; these should never be in the allow-list anyway)
  • path matches node_modules/*, .git/*block (noise, not the user's work)

For multi-project setups (one agent working across many repos), the pattern is one allow-list per active project. The agent's filesystem scope updates as the user switches projects (via Roots).

For multi-tenant SaaS setups (one agent per customer), each tenant has their own Filesystem MCP server with their own allow-list. No cross-tenant file access.

Quickstart

# Option 1: NPX with explicit allowed directories
npx -y @modelcontextprotocol/server-filesystem \
  /home/user/projects \
  /tmp/agent-scratch

# Option 2: Docker with mounted volumes
docker run -i --rm \
  -v /home/user/projects:/projects:rw \
  -v /tmp/agent-scratch:/scratch:rw \
  mcp/filesystem /projects /scratch

Configuration:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y", "@modelcontextprotocol/server-filesystem",
        "/home/user/projects",
        "/tmp/agent-scratch"
      ]
    }
  }
}

First prompts:

"Read all .ts files in /projects/repo/src and summarize the architecture"
"Find every TODO in /projects/repo"
"Edit /projects/repo/src/config.ts to use the PORT environment variable"
"Create a new directory /projects/repo/src/auth with an empty index.ts"
"Search for usage of the deprecated 'moment' library across all .ts files"

Use Cases

Code review: "Read the 5 changed files in this PR, summarize the changes, identify issues." Multi-file read → analysis → structured review.

Refactoring: "Find every usage of the deprecated 'moment' library and propose replacements." Search → multi-file read → migration plan → edits.

Project bootstrapping: "Create a new TypeScript project skeleton: package.json, tsconfig.json, src/index.ts, README.md, .gitignore." Multi-file create with templated content.

Documentation generation: "Read the source code, generate API documentation, write to docs/api.md." Code analysis → doc generation → file write.

Log analysis: "Read the last 100 lines of /var/log/app.log, summarize the errors, suggest fixes." File read → analysis → structured summary.

Image review: "Read the architecture diagram and explain the system's components." Image read → visual reasoning → structured explanation.

Codebase exploration: "Walk the project tree, summarize the structure, identify the main modules." Recursive listing → tree construction → summary.

Migration scripts: "Find every file that imports 'moment', for each, replace with 'date-fns' equivalents." Code search → multi-file edit → verify.

Configuration management: "Update the .env.example with the new feature flags, ensuring no actual secrets are committed." Templated file write with safety checks.

Test generation: "For each .ts file in src/, generate a corresponding .test.ts file in tests/." Multi-file creation with consistent patterns.

Code cleanup: "Find all unused exports and remove them." Code analysis → multi-file edit.

Project audit: "Find all files larger than 1MB, list them with sizes, flag for review." Directory walk with size analysis.

Git workflow: "Read the diff in src/, suggest a commit message, write it to COMMIT_MSG." Diff read → message generation → file write.

Documentation sync: "Update the README to reflect the new API endpoints from src/api/routes.ts." Code reading → doc regeneration → file write.

Backup automation: "Copy every .ts file in src/ to backup/src/ with today's date suffix." Recursive copy.

Dependency analysis: "Read package.json, identify outdated dependencies, suggest updates." JSON parsing → version analysis → recommendations.

Schema migration: "For each .sql file in migrations/, generate a corresponding rollback script." SQL parsing → reverse-script generation.

Codebase metrics: "Count lines of code per file, group by directory, generate a metrics report." Recursive analysis → aggregation → structured report.

Setup automation: "Create a new project from the template at /templates/nextjs-app, configure for our domain." Template copy → configuration → verification.

Workspace organization: "Move all .log files older than 30 days to /archive/." File metadata → age check → move operation.

The Sandboxing Pattern

The Filesystem MCP server's defining innovation — explicit allowed-directories at startup — is the design lesson every "system-resource" MCP server should copy.

Why explicit allow-lists win:

  • Deny-by-default — no resource is accessible unless explicitly granted
  • Configuration-level safety — the operator defines the scope at setup, not per-call
  • Inspectablelist_allowed_directories shows the agent what it can touch
  • No escape — path traversal, symlink tricks, relative path games all fail
  • Per-tenant isolation — one Filesystem server per tenant, each with their own allow-list
  • Container-friendly — the Docker pattern uses volume mounts, so the operator controls filesystem isolation at the OS level

For any MCP server that touches a system resource — filesystem, network, processes, environment variables — the same pattern applies: explicit allow-list at startup, deny-by-default, no escape paths. The agent's capabilities are bounded by the operator's configuration, not by tool naming conventions or hope.

Bottom Line

The Filesystem MCP Server is the local-file-access default for AI agents in 2026. ~14 focused tools (read, write, edit, search, directory, metadata), explicit allowed-directories sandboxing, Roots-aware dynamic updates, image support, MIT-licensed, official Anthropic-maintained. Available via NPX or Docker.

For any agent that does real work — code review, refactoring, project bootstrapping, log analysis, documentation generation, file migration — this is the bridge. The agent operates on files within the allow-list, can't escape the boundary, every operation is audited.

For the broader MCP ecosystem, the Filesystem pattern is the design lesson every "system-resource" MCP server should copy. Explicit allow-lists at startup. Deny-by-default. No escape paths. When the security boundary is configuration-level, the agent's blast radius is bounded.

npx -y @modelcontextprotocol/server-filesystem /path/to/allowed/dir (or docker run -i --rm -v /path:/mount:rw mcp/filesystem /mount) and your agent has bounded file access.


MCP Spotlight is a series covering servers that give AI agents real capabilities. Every server is evaluated for design clarity, ecosystem impact, and integration fit with Facio's HITL-first agent runtime.

Keep reading

More on Engineering

View category
Jul 13, 2026Engineering

MCP Spotlight: Stripe MCP Server — The Payments Bridge With Restricted API Keys, Customer-Portal Scope Isolation, and the Money-Movement Default for Agents

The official Stripe MCP Server by Stripe — ~30 focused tools covering customers, payment intents, subscriptions, products, invoices, refunds, disputes, payouts. Restricted API Key support for per-resource + per-action scope isolation. PCI-scope minimization, webhook-first event model. The payment-automation default for AI agents in 2026.

Jul 12, 2026Engineering

MCP Spotlight: Brave Search MCP Server — The Web-Wide Search Bridge With Independent Index, Local-First Privacy Options, and the Research-Default Reference

The official Brave Search MCP Server by Brave Software — ~8 focused tools covering web, local, image, video, and news search. Brave's independent web crawler (no Google/Bing dependency), privacy-first (no user tracking), 2000 queries/month free tier, EU presence. The independent-index search default for AI agents in 2026.

Jul 11, 2026Engineering

MCP Security Architecture 2026: Threat Models, Sandboxing, and the Defense-in-Depth Layers Every Production Agent Deployment Needs

The defense-in-depth reference architecture every team deploying MCP in production needs. Six layers: server verification → process sandboxing → credential isolation → per-tool RBAC → HITL approval → audit trail. Plus prompt-injection defense and multi-agent trust boundaries. Companion to the MCP Spotlight series.