github
MCPReads and writes GitHub issues, pull requests, files and repository metadata.
Reads, writes and lists files in directories you explicitly allow.
Claude Code
$ claude mcp add filesystem -- npx @modelcontextprotocol/server-filesystem .
Codex
$ codex mcp add filesystem -- npx @modelcontextprotocol/server-filesystem .
Cursor
{ "mcpServers": { "filesystem": { "command": "npx", "args": [ "@modelcontextprotocol/server-filesystem", "." ] } } }
Add it to mcp.json.
Gemini CLI
$ gemini mcp add filesystem npx @modelcontextprotocol/server-filesystem .
GitHub Copilot
$ copilot mcp add filesystem -- npx @modelcontextprotocol/server-filesystem .
OpenCode
{ "mcp": { "filesystem": { "type": "local", "command": [ "npx", "@modelcontextprotocol/server-filesystem", "." ] } } }
Add it to opencode.json.
Windsurf
{ "mcpServers": { "filesystem": { "command": "npx", "args": [ "@modelcontextprotocol/server-filesystem", "." ] } } }
Add it to mcp_config.json.
From the README
Read/write files
Create/list/delete directories
Move files/directories
Search files
Get file metadata
Directory access control from command-line arguments, with Roots as a deprecated, 2025-era convenience
Serves both protocol eras on stdio
2026-07-28 clients (server/discover, no handshake) and 2025-era clients (initialize)
Security report
Low risk
Known flaws
None known
Signed build
Yes
Build provenance published
Maintained
Jul 23, 2026
Last push
Licence
Not published
Runs as
npx
On your machine
Deprecated
No
Signals from public registries, not an audit. Checked Nov 11, 2026.
Node.js server implementing Model Context Protocol (MCP) for filesystem operations.
Published on npm as @modelcontextprotocol/server-filesystem.
server/discover, no handshake) and 2025-era clients (initialize)The server may touch only its allowed directories. Pass them on the command line. A 2025-era client that supports Roots can also replace them at runtime, but Roots is deprecated as of protocol version 2026-07-28 and a 2026-07-28 connection cannot use it.
Specify Allowed directories when starting the server:
mcp-server-filesystem /path/to/dir1 /path/to/dir2
Options may come before, between or after the directories: --read-only, --read-only-dir <path> (both below) and --confine-roots (under Method 2).
This is the only method that works on every protocol version, so it is the one to use.
Add --read-only to serve only the tools that cannot change the filesystem:
mcp-server-filesystem --read-only /path/to/dir1 /path/to/dir2
The server then registers only the tools annotated readOnlyHint: true in the Tool annotations table, the ones that read and list. Every tool not annotated readOnlyHint: true, that is every tool that writes (such as write_file and edit_file), is left out, so a client never lists it and a call to it fails as an unknown tool. A tool added later follows the same rule through its annotation. The server enforces this, whatever the client is configured to allow, and it works the same with npx as with Docker. It applies on both protocol eras, and to directories that come from a client's Roots.
The flag may appear anywhere among the arguments. -- ends the options, so a directory literally named --read-only can be given after it.
Read-only mode covers every allowed directory. To make only some of them read-only, use --read-only-dir below.
Add --read-only-dir <path> to make one directory read-only while the others stay writable. Repeat it for each directory to protect:
mcp-server-filesystem --read-only-dir /path/to/reference /path/to/workspace
write_file, append_file, edit_file, create_directory, move_file and copy_file) stays listed, since the other directories are writable, but refuses a target inside a read-only directory with an error such as Access denied - read-only directory: /path/to/reference/notes.md is in /path/to/reference, which the server was started with --read-only-dir. move_file is refused when either its source or its destination is inside one or contains one, so a protected directory cannot be carried away by moving its parent; copy_file may copy out of one, never into it. edit_file is refused there even with dryRun.--confine-roots.list_allowed_directories lists the read-only directories after the allowed ones, and the server logs them to stderr at startup.The option may appear anywhere among the arguments, and takes the next argument as its directory, whatever it is. -- ends the options, so after it --read-only-dir is a directory name. With --read-only as well, every write tool is withheld anyway. For defence in depth, make the protected directories read-only at the operating-system level as well, with file permissions or, with Docker, a bind mount's ro flag.
A client that connects with a 2025-era protocol version (the initialize handshake) and supports Roots can dynamically update the Allowed directories.
Roots notified by Client to Server, completely replace any server-side Allowed directories when provided.
To keep a client's Roots inside the directories you gave on the command line, add --confine-roots:
mcp-server-filesystem --confine-roots /path/to/dir1 /path/to/dir2
The client's Roots can then narrow the command-line directories but never replace or widen them. The server allows the overlap of the two:
/) is narrowed to that directory.This suits an operator who decides what may be shared (the command line) while letting a client say what it wants to work on (its Roots), and it keeps a client from discarding the command-line directories by advertising its working directory. Without command-line directories the flag has no effect, and the server warns at startup. Without the flag, Roots replace the command-line directories as described above.
A Root reached through a symlink is allowed in both its advertised form and its resolved form, as a command-line directory is: a Root of file:///tmp/project on macOS allows /tmp/project and /private/tmp/project. Every requested path is still resolved and checked against the resolved directories, so a symlink inside a Root that points outside it is refused.
Important: If server starts without command-line arguments AND a 2025-era client doesn't support roots protocol, the server fails at initialization: it logs the reason to stderr, closes the connection and exits with status 1. A client that supports roots but provides none (or none that are valid) keeps the connection, with no allowed directories until it sends roots/list_changed with valid roots.
The 2026-07-28 protocol has no initialize handshake and no server-to-client roots/list request, so a 2026-07-28 client's roots are never asked for: the command-line directories are the whole allow-list. A server started with none answers every tool call on such a connection with an error saying so.
The server's directory access control follows this flow:
Server Startup
Client Connection
server/discover (or any request carrying the per-request _meta envelope): the server uses the command-line directories, and steps 3 and 4 do not applyinitialize with its capabilities, and the server checks whether it supports roots (capabilities.roots)Roots Protocol Handling (2025-era clients that support roots)
roots/list--confine-roots, with their overlap with the command-line directories)notifications/roots/list_changedFallback Behavior (2025-era clients that don't support roots)
Access Control
list_allowed_directories tool to see current directoriesinitialize, after each Roots update, and when a withdrawal leaves none. For example:
Effective allowed directories (from the client's Roots, which replaced the command-line directories):
/Users/username/project
file.txt:stream, file.txt::$DATA) is refused with "Access denied - NTFS alternate data stream paths are not supported", even inside an allowed directory: a colon is accepted only as a drive letter's (C:\, \\?\C:\). A stream holds data that no directory listing or diff of the file shows. On macOS and Linux a colon is an ordinary file-name character and is not refusedCON, PRN, AUX, NUL, COM1-COM9, LPT1-LPT9, in any case and with or without an extension, such as NUL.txt) is refused with "Access denied - Windows reserved device names ... are not supported", and one any of whose components ends in a dot or a space (file.txt., dir \file.txt) with "Access denied - Windows path components ending in a dot or a space are not supported". Windows opens the device rather than a file in the directory, and strips trailing dots and spaces so the name refers to a different file. . and .. are not affected. On macOS and Linux these are ordinary file names and are not refusedNote: The server will only allow operations within directories specified either via args or, for a 2025-era client, via Roots.
This repository demonstrates how to use Claude Code to do real engineering work, not just writing code. 本项目是极客时间专栏 《Claude Code 工程化实战》 的官方配套示例仓库,目标就是: 👉 把 Claude Code 从“对话式编码工具”,变成 可设计、可复用、可治理的工程系统。
Reads and writes GitHub issues, pull requests, files and repository metadata.
Ships with ai-learning-coach: 用真实 Agent 项目学会 TypeScript。教练记住你卡在哪里,带你预测、调试、修改,并用实际证据判断下一步。 首要面向已经会 Java 或其他后端语言、希望进入 TypeScript /…