read-only-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@read-only-mcplist the files in the docs folder"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
readonly-mcp
A minimal Model Context Protocol server that exposes read-only access to a single directory tree over the stdio transport.
Usage
npm install
npm run build
node dist/index.js /path/to/allowed/rootThe allowed root directory is the sole command-line argument. It must exist and be a directory, or the server exits with an error before accepting any request.
MCP client configuration:
{
"mcpServers": {
"readonly": {
"command": "node",
"args": ["/absolute/path/to/readonly-mcp/dist/index.js", "/path/to/allowed/root"]
}
}
}Related MCP server: mcp-readonly-code-server
Tools
All path arguments may be absolute or relative to the allowed root.
list_directory(path)
Lists the entries of a directory. Each line is prefixed with [DIR], [FILE], [LINK],
or [OTHER]. Errors if the path is not a directory.
read_file(path)
Returns the full UTF-8 contents of a file. The file is opened with O_RDONLY | O_NOFOLLOW.
Directories, non-regular files (sockets, devices, FIFOs), and files larger than 10 MB are
rejected.
search_files(path, pattern)
Recursively walks the tree from path and returns the relative paths of entries whose
name matches pattern. A pattern containing * or ? is treated as a case-insensitive
glob over the entry name (*.ts); otherwise it is a case-insensitive substring match
(config). Symlinks are never followed, which prevents both traversal escapes and
directory cycles. Results are capped at 1000 and the output says so when truncated.
get_file_info(path)
Returns metadata for a file or directory: relative path, absolute path, type, size in bytes, modified/created/accessed timestamps (ISO 8601), and octal permission bits.
Path containment
Every path argument passes through resolveWithinRoot() before any filesystem operation:
Reject empty paths and paths containing a null byte.
Expand a leading
~, then resolve to an absolute path (relative paths resolve against the allowed root). This collapses..segments.Reject if the absolute path is not the root itself or a descendant of it.
realpath()the result to resolve every symlink in the path, including the final component.Reject again if the real path escapes the root.
Containment is a prefix check against ALLOWED_ROOT + path.sep, so a sibling directory
whose name merely starts with the root's name (/data/rootabc vs /data/root) does not
pass. The root itself is stored as its own realpath() at startup, so the comparison is
real-path against real-path.
Verified behaviors: ../outside/secret.txt, /etc/passwd, sub/../../outside/secret.txt,
a symlinked file pointing outside the root, and a symlinked directory pointing outside the
root are all rejected with access denied.
No write capability
This server cannot modify the filesystem. There is no write_file, edit_file,
delete_file, move_file, or mkdir tool — not as a stub, not disabled, not anywhere.
An unrecognized tool name returns unknown tool: <name>.
The entire implementation is one file, src/index.ts. The only filesystem
calls it makes are:
Call | Purpose |
| resolve symlinks for containment checks |
| type, size, timestamps, permissions |
| list directory entries |
| open files for reading only |
| read contents, release the descriptor |
No writeFile, appendFile, unlink, rm, rmdir, mkdir, rename, copyFile,
truncate, chmod, chown, utimes, link, symlink, or createWriteStream appears in
the source. You can confirm this yourself:
grep -nE '\b(writeFile|appendFile|unlink|rm|rmdir|mkdir|rename|copyFile|truncate|ftruncate|chmod|chown|utimes|link|symlink|createWriteStream|write)\(|O_WRONLY|O_RDWR|O_CREAT|O_TRUNC|O_APPEND' src/index.tsThe only hits are the four process.stderr.write(...) calls used for the usage message,
the two startup errors, and the startup banner. Nothing touches the filesystem. Run the
same grep over dist/index.js after npm run build to audit the compiled output.
Files are opened with the O_RDONLY flag at the OS call level, so even a bug elsewhere in
the process cannot write through a descriptor this server holds.
The server writes exactly one line to stderr at startup (the root it is serving) and otherwise speaks only MCP over stdout.
This server cannot be deployed
Maintenance
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Search and read Empryo's documentation. Read-only, no auth, no local access.
Read-only MCP server exposing a user ORANO library to their own AI agent.
Read-only MCP server for the OPERANT AI operating-agent calibration benchmark.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceStdio MCP server for sandboxed file access — read files, search content, safely edit with checksums, and manage file structure.4 npmISC
- FlicenseBqualityCmaintenanceA read-only MCP server that exposes a local code workspace to AI clients via stdio, providing file browsing and text search capabilities with path safety rules.1-
- AlicenseNot gradedqualityAmaintenanceA small filesystem MCP server that reads and writes files under one confined root over stdio, with paginated tools and strict change-detection. It enables safe, deterministic file access for agentic runtimes and MCP clients.113 npmMIT
- AlicenseAqualityAmaintenanceEnables AI clients to inspect and carefully edit a bounded local workspace via stdio, with a read-only default, conflict-safe updates, and no network listener or telemetry.101Apache 2.0