Skip to main content
Glama
MartinSchoeler

read-only-mcp

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

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

  1. Reject empty paths and paths containing a null byte.

  2. Expand a leading ~, then resolve to an absolute path (relative paths resolve against the allowed root). This collapses .. segments.

  3. Reject if the absolute path is not the root itself or a descendant of it.

  4. realpath() the result to resolve every symlink in the path, including the final component.

  5. 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

fs.realpath

resolve symlinks for containment checks

fs.stat / handle.stat

type, size, timestamps, permissions

fs.readdir

list directory entries

fs.open(p, O_RDONLY | O_NOFOLLOW)

open files for reading only

handle.readFile / handle.close

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.ts

The 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.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Stdio MCP server for sandboxed file access — read files, search content, safely edit with checksums, and manage file structure.
    16
    ISC
  • F
    license
    B
    quality
    C
    maintenance
    A 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

View all related MCP servers

Related MCP Connectors

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

  • Query SEC EDGAR filings, XBRL financials, and company data through MCP. STDIO & Streamable HTTP.

  • Federated commerce search across independent WooCommerce merchants. Keyless, read-only MCP server.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MartinSchoeler/read-only-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server