Providers: Amazon S3 · Azure Blob Storage · Google Cloud Storage · MinIO · RustFS · Cloudflare R2 · Backblaze B2 · Wasabi · LocalStack · SQLite · In-Memory
Table of Contents
- What it does
- Quick start
- Interactive Shell
- Transports
- Authentication & Authorization
- Production Features
- CLI Reference
- Provider Setup
- MCP Client Config
- Tool Reference
- Architecture: VFS
- Caching
- Programmatic Usage
- MCP Inspector
- Development & Testing
- AI Agent Skill
- Documentation
- License
What it does
@nogoo9/mcp-server-cloud-fs exposes all 14 tools defined by mcp-server-filesystem — same tool names, same parameter schemas — over cloud object storage. Drop it into any MCP client config that currently points at mcp-server-filesystem and your AI assistant gains read/write access to S3, Azure Blob Storage, or Google Cloud Storage buckets.
It also includes 5 extended tools inspired by claude-code's filesystem tool surface: line-range reads, byte-range chunk reads, in-process regex search (single file and multi-file), server-side copy, and opt-in deletion. Plus 6 cloud-native tools (presigned URLs, object metadata/tags, tag-based search, version history, version restore), 2 AI-native tools (schema extraction, file summarization), and 1 macro tool (patch_file for atomic diffs).
A Virtual Filesystem (VFS) layer provides FUSE-like cache coherence with ETag-based concurrency control, a shell tool lets you run POSIX-like commands (ls, grep, jq, cat | wc, etc.) against cloud storage, and the package is available as a programmatic npm library.
v0.7.0 Highlights
- Dynamic tool surface reduction: scope-aware tool filtering — clients only see tools they're authorized to use
- DLP content sanitization: regex-based middleware redacts PII, API keys, and credentials from tool responses (
--enable-dlp) - AI-native tools:
get_file_schemaextracts CSV/JSON structure;summarize_filereturns compact head/tail previews - ETag concurrency control: SHA-256 content-addressable ETags with
expected_etagconflict detection onedit_fileandpatch_file patch_filemacro tool: atomic read-diff-write in a single tool call — supports unified diffs and line-range replacements
v0.6.0 Highlights
- Cloud-native tools: presigned URLs, object metadata/tags, version history, version restore
- Byte-range reads:
read_file_chunkfetches specific byte ranges without downloading the full object - Structured audit logging: tool invocation audit trail with pluggable sinks (stderr, file)
- Multi-provider routing:
MultiProviderserves S3 + Azure + GCS from a single server instance - Azure Managed Identity:
DefaultAzureCredentialfor OIDC and federated auth - Connection health-check: startup credential validation with diagnostic reporting
- MCP Resources: browse cloud storage as native MCP Resources (no tool calls needed)
- Structured errors:
CloudErrorwith typed codes and provider-specific error mappers
v0.5.0 Highlights
- Interactive TUI (
cloud-fs): Terminal shell withcd, tab completion, and command history - Multi-transport: STDIO (default), Streamable HTTP, and WebSocket
- Dual runtime: Bun-native and Node.js support (HTTP transport + SQLite provider)
- OAuth 2.1: Built-in auth server or external IdP token validation
- ext-auth extensions: Client Credentials (M2M) and Enterprise-Managed Authorization (SSO)
- Production hardening: Rate limiting, CORS, security headers, health checks, structured logging
- AI agent skill: Installable
skills/cloud-fsfor Claude Code, Gemini CLI, and other AI assistants
Quick start
Local (STDIO — default)
npx @nogoo9/mcp-server-cloud-fs s3 s3://my-bucket
Remote (HTTP)
# Bun (zero Express dependency)
bunx @nogoo9/mcp-server-cloud-fs s3 s3://my-bucket --transport http --port 3000
# Node.js (requires express peer dep)
npx @nogoo9/mcp-server-cloud-fs s3 s3://my-bucket --transport http --port 3000
Remote (WebSocket — Bun only)
bunx @nogoo9/mcp-server-cloud-fs s3 s3://my-bucket --transport ws --port 3000
Demo (no cloud credentials needed)
bunx @nogoo9/mcp-server-cloud-fs memory mem://demo --enable-shell --seed-demo
Interactive Shell (cloud-fs)
Drop into an interactive terminal for exploring and managing cloud storage — no MCP client needed:
# S3
npx -p @nogoo9/mcp-server-cloud-fs cloud-fs s3 s3://my-bucket
# In-memory demo with sample files
npx -p @nogoo9/mcp-server-cloud-fs cloud-fs memory mem://demo --seed-demo
# With a config file (cloud-fs.json in CWD)
npx -p @nogoo9/mcp-server-cloud-fs cloud-fs
Features
cdnavigation —cd data,cd ..,cd /with dynamic prompt showing current directory- Tab completion — context-aware path and command completion
- Command history — persistent across sessions (
~/.cloud-fs_history) - Relative paths — all commands resolve relative to
cwd, just like a real shell - 19 built-in commands —
ls,cat,head,tail,cp,mv,rm,mkdir,touch,stat,find,grep,wc,du,echo,tee,diff,jq,cd - Pipes & redirects —
cat config.json | jq '.database',echo hello > file.txt
Local development
bun src/cli-tui.ts memory mem://demo --seed-demo
Transports
The server supports three MCP transports, selected via --transport:
Streamable HTTP
Implements the MCP Streamable HTTP specification with a single /mcp endpoint for POST (requests), GET (SSE notifications), and DELETE (session termination).
Dual runtime support:
- Bun: Uses
WebStandardStreamableHTTPServerTransportwithBun.serve()directly — zero Express dependency, maximum performance. - Node.js: Falls back to
StreamableHTTPServerTransportwith Express. Requiresexpressas an optional peer dependency (npm install express).
Runtime is auto-detected at startup.
Session management:
Sessions use UUID v7 (RFC 9562) — time-ordered and K-sortable, making them ideal for logging, debugging, and database indexing. Sessions are tracked via the Mcp-Session-Id header.
Resumability:
When an EventStore is configured, clients can reconnect and resume receiving messages from where they left off via the Last-Event-ID SSE header.
# Basic HTTP server
cloud-fs-mcp s3 s3://my-bucket --transport http --port 3000
# With authentication
cloud-fs-mcp s3 s3://my-bucket --transport http --port 3000 --auth builtin --auth-issuer https://my-server.example.com
# Production deployment
cloud-fs-mcp s3 s3://my-bucket \
--transport http --port 3000 --host 0.0.0.0 \
--auth external --auth-jwks-uri https://login.example.com/.well-known/jwks.json \
--cors-origin https://app.example.com \
--rate-limit 60 --rate-limit-burst 10 \
--security-headers \
--request-logging
WebSocket
Bun-native WebSocket transport using Bun.serve() with WebSocket upgrade handling. Provides lower latency than HTTP for high-frequency tool invocations.
- JSON-RPC message framing over WebSocket
- UUID v7 session assigned on upgrade
- WS ping/pong heartbeat for connection liveness
cloud-fs-mcp s3 s3://my-bucket --transport ws --port 3000
Authentication & Authorization
Authentication is disabled by default and only applies to HTTP/WS transports. STDIO mode never requires auth.
Auth modes
Built-in OAuth server (--auth builtin)
The server runs a full OAuth 2.1 Authorization Server using the MCP SDK's mcpAuthRouter():
- Authorization Code + PKCE (mandatory) — interactive user consent flow
- Dynamic Client Registration — MCP clients auto-register on first connect
- Refresh token rotation — single-use refresh tokens prevent replay
- Metadata discovery —
/.well-known/oauth-authorization-server(RFC 8414) and/.well-known/oauth-protected-resource(RFC 9728)
cloud-fs-mcp s3 s3://my-bucket \
--transport http --port 3000 \
--auth builtin --auth-issuer https://my-server.example.com
External IdP (--auth external)
The server only validates bearer tokens — it does not issue tokens. Use this when you have an existing identity provider.
- JWKS validation — fetches and caches signing keys from your IdP
- JWT verification — checks signature, issuer, audience, expiry
- Token introspection — fallback for opaque tokens
cloud-fs-mcp s3 s3://my-bucket \
--transport http --port 3000 \
--auth external \
--auth-jwks-uri https://login.example.com/.well-known/jwks.json \
--auth-audience https://cloud-fs.example.com
ext-auth: Client Credentials (M2M)
Implements the MCP Client Credentials extension for machine-to-machine authentication without user interaction. Designed for CI/CD pipelines, background services, and automated workflows.
- JWT assertion auth (
private_key_jwtper RFC 7523) — recommended - Client secret auth (
client_secret_basic) — simpler but less secure - No user interaction required — tokens granted based on pre-registered client credentials
cloud-fs-mcp s3 s3://my-bucket \
--transport http --port 3000 \
--auth builtin --auth-issuer https://my-server.example.com \
--auth-client-credentials
ext-auth: Enterprise-Managed Authorization (SSO)
Implements the MCP Enterprise-Managed Authorization extension for seamless SSO via your organization's Identity Provider.
How it works:
- User logs in to the MCP Client via the enterprise IdP (OpenID Connect or SAML)
- Client exchanges the ID Token for an Identity Assertion JWT Authorization Grant (ID-JAG) via Token Exchange (RFC 8693)
- Client presents the ID-JAG to this server's Authorization Server (RFC 7523)
- Server validates the ID-JAG and issues an access token
Benefits:
- Zero manual authorization per MCP Server — SSO handles everything
- Enterprise admins control which users/groups can access which MCP servers
- Granular scope enforcement via IdP policies
cloud-fs-mcp s3 s3://my-bucket \
--transport http --port 3000 \
--auth builtin --auth-issuer https://my-server.example.com \
--auth-enterprise-idp https://acme.okta.com
OAuth Scopes
When auth is enabled, tool access is controlled by granular scopes:
When grantedScopes is set (via OAuth tokens), tools outside the granted scopes are not registered — they don't appear in tools/list at all, reducing LLM prompt token waste and preventing tool hallucination.
Tokens with insufficient scopes receive a clear error response indicating which scope is required.
Production Features
Health Checks
HTTP/WS transports expose Kubernetes-convention health endpoints:
Configure your orchestrator's liveness and readiness probes to use these endpoints.
Rate Limiting
Token bucket rate limiting protects against abuse. Disabled by default.
- In-memory — per-IP/per-client counters for single-process deployments
- Redis — distributed rate limiting for multi-instance deployments (uses existing optional
ioredispeer dep) - Returns
429 Too Many RequestswithRetry-Afterheader when limits are exceeded
# 60 requests/minute with burst of 10
cloud-fs-mcp s3 s3://my-bucket --transport http \
--rate-limit 60 --rate-limit-burst 10
CORS
Cross-Origin Resource Sharing for browser-based MCP clients:
- Strict origin allowlist — no wildcards in production
- Exposes
Mcp-Session-IdandMcp-Protocol-Versionheaders - Localhost auto-allows
*when--host 127.0.0.1(dev convenience)
cloud-fs-mcp s3 s3://my-bucket --transport http \
--cors-origin https://app.example.com \
--cors-origin https://staging.example.com
Structured Request Logging
JSON audit trail to stderr for compliance and debugging:
{"ts":"2026-05-12T12:00:00Z","sessionId":"019...","tool":"read_file","user":"[email protected]","latencyMs":42,"status":200}
Enable with --request-logging.
DNS Rebinding Protection
Automatically applied when binding to localhost addresses. Validates the Host header against allowed hostnames to prevent DNS rebinding attacks.
Security Headers
Opt-in HTTP response hardening via nosecone — a framework-agnostic security headers library. Works with both Bun-native and Node/Express transports.
When enabled, every HTTP response includes standard security headers:
Content-Security-PolicyStrict-Transport-SecurityX-Content-Type-Options: nosniffX-Frame-OptionsCross-Origin-Opener-PolicyCross-Origin-Resource-PolicyReferrer-Policy- And more (see nosecone defaults)
# Enable with defaults
cloud-fs-mcp s3 s3://my-bucket --transport http --security-headers
# Custom configuration via inline JSON
cloud-fs-mcp s3 s3://my-bucket --transport http \
--security-headers-config '{"contentSecurityPolicy":false}'
# Custom configuration via file
cloud-fs-mcp s3 s3://my-bucket --transport http \
--security-headers-config-file ./nosecone.json
Note: Requires the
noseconepeer dependency:npm install nosecone
CLI Reference
cloud-fs-mcp <provider> <root-uri> [root-uri...] [options]
Providers
Options
Transport & Network
Authentication
Production
Storage & Cache
Tools
Credentials are always sourced from SDK credential chains — never CLI flags.
Provider Setup
AWS S3
Credentials are read from the standard AWS credential chain: AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars, ~/.aws/credentials, EC2 instance profiles, and so on.
cloud-fs-mcp s3 s3://my-bucket --region us-east-1
S3-compatible storage
Any S3-compatible backend works via --endpoint. All use the standard AWS credential chain (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY).
# MinIO
export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin
cloud-fs-mcp s3 s3://my-bucket --endpoint http://minio:9000
# Cloudflare R2
export AWS_ACCESS_KEY_ID=<r2-access-key-id>
export AWS_SECRET_ACCESS_KEY=<r2-secret-access-key>
cloud-fs-mcp s3 s3://my-bucket --endpoint https://<account-id>.r2.cloudflarestorage.com --region auto
# Backblaze B2
export AWS_ACCESS_KEY_ID=<b2-key-id>
export AWS_SECRET_ACCESS_KEY=<b2-application-key>
cloud-fs-mcp s3 s3://my-bucket --endpoint https://s3.us-west-004.backblazeb2.com --region us-west-004
# LocalStack
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
cloud-fs-mcp s3 s3://my-bucket --endpoint http://localhost:4566 --region us-east-1
TLS with private CA: For MinIO, RustFS, or Ceph with a self-signed certificate, add
--ca-file /path/to/ca.pem.
Azure Blob Storage
Uses DefaultAzureCredential — works with AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET env vars, managed identity, az login, and so on.
cloud-fs-mcp azure az://my-container
Google Cloud Storage
Uses Application Default Credentials (ADC). Set GOOGLE_APPLICATION_CREDENTIALS or run gcloud auth application-default login.
cloud-fs-mcp gcs gs://my-bucket
In-Memory (ephemeral)
Zero-config, zero-dependency provider. All data lives in a Map and is lost when the process exits.
cloud-fs-mcp memory mem://demo --enable-shell
SQLite (persistent local)
Persistent local storage using WAL mode. Dual-runtime: uses bun:sqlite on Bun, better-sqlite3 on Node.js (install as peer dep: npm install better-sqlite3).
cloud-fs-mcp sqlite sqlite://my-bucket --sqlite-db /tmp/cloud-fs.db --enable-shell
MCP Client Config
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"cloud-fs": {
"command": "npx",
"args": ["-y", "@nogoo9/mcp-server-cloud-fs", "s3", "s3://my-bucket"]
}
}
}
Claude Code
.mcp.json in your project root:
{
"mcpServers": {
"cloud-fs": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@nogoo9/mcp-server-cloud-fs", "s3", "s3://my-bucket"]
}
}
}
Remote HTTP client
{
"mcpServers": {
"cloud-fs": {
"type": "streamable-http",
"url": "https://cloud-fs.example.com/mcp"
}
}
}
Tool Reference
All paths are cloud URIs — e.g. s3://my-bucket/path/to/file.txt. The server validates every path against the configured root URIs at startup; requests outside allowed roots are rejected.
Read tools
Write tools
Directory tools
Move, Copy & Delete tools
Search tools
Info tools
✨ = Extended tool
Cloud-native tools ☁️
☁️ = Cloud-native tool (requires provider support)
AI-native tools 🧠
🧠 = AI-native tool (reduces LLM context token waste)
Macro tools 🩹
🩹 = Macro tool (combines read + transform + write)
Shell tool ⚡
Built-in commands: ls, cat, head, tail, cp, mv, rm, mkdir, touch, stat, find, grep, wc, du, echo, tee, diff, jq, cd
Relative paths
All shell commands (and all other tools) support relative paths — you don't need to type the full URI every time. Paths without a scheme prefix (s3://, mem://, etc.) are resolved relative to the first configured root:
# With root s3://my-bucket/data, these are equivalent:
shell "cat config.json"
shell "cat s3://my-bucket/data/config.json"
# Subdirectories work naturally:
shell "ls logs/"
shell "cat logs/app.log | grep ERROR"
# ls with no args lists the root's contents:
shell "ls"
# find with no args searches from the root:
shell "find -name '*.json'"
Standard . and .. are normalized, with .. traversal blocked at the root boundary for security.
Examples
# List root contents
shell "ls -l"
# JSON query with jq
shell "cat config.json | jq '.database.port'"
# Search and count
shell "grep -i error server.log | wc -l"
# Write files
shell "echo hello world > greeting.txt"
# Copy and diff
shell "cp config.json config.backup.json"
shell "diff config.json config.backup.json"
# Full URIs still work for cross-root access
shell "cat s3://other-bucket/file.txt"
⚡ Requires
--enable-shell.rmandmvadditionally require--enable-delete.
Architecture: Virtual Filesystem (VFS)
All tool operations are mediated through a Virtual Filesystem (VFS) layer inspired by FUSE.
┌─────────────────────────────────────────────────────────┐
│ MCP Tool Handlers (read, write, list, stat, …) │
├─────────────────────────────────────────────────────────┤
│ VirtualFS │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Inodes │ │ DirIndex │ │ Tombstones│ │
│ │ (metadata)│ │ (parents) │ │ (deleted) │ │
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
│ └──────────────┴─────────────┘ │
│ ⇣ Overlay (in-memory, persisted to CacheStore) │
├─────────────────────────────────────────────────────────┤
│ CacheStore (Memory / Filesystem / Redis) │
├─────────────────────────────────────────────────────────┤
│ StorageProvider (S3 / Azure Blob / GCS / Memory / SQL) │
└─────────────────────────────────────────────────────────┘
VFS metadata is persisted to the CacheStore under __vfs__/* keys. On startup, VirtualFS.hydrate() restores state; corrupted data is silently discarded.
Caching
Writes land in cache immediately (marked dirty), flushed after debounce window (default: 2s). Graceful shutdown flushes all dirty entries before exit. Pass-through mode (--no-cache) sends every operation directly to the provider.
⚠️ Redis TLS: The server warns at startup when
REDIS_URLuses unencryptedredis://. Userediss://for TLS-encrypted connections in production.
Custom CA Certificates
Use --ca-file <path> to supply a PEM CA bundle for S3-compatible endpoints (MinIO, RustFS) and Redis running with a private CA:
# S3-compatible with self-signed CA
cloud-fs-mcp s3 s3://my-bucket \
--endpoint https://minio.internal:9000 \
--ca-file /etc/ssl/certs/my-ca.pem
# Redis with private CA
REDIS_URL=rediss://redis.internal:6380 \
cloud-fs-mcp s3 s3://my-bucket --cache-store redis \
--ca-file /etc/ssl/certs/my-ca.pem
For runtime-wide CA trust (all providers + Redis), use the standard NODE_EXTRA_CA_CERTS env var instead:
NODE_EXTRA_CA_CERTS=/etc/ssl/certs/my-ca.pem cloud-fs-mcp s3 s3://my-bucket
Programmatic Usage (npm library)
import {
createMcpServer, VirtualFS, MemoryStore,
S3Provider, parseUri,
} from "@nogoo9/mcp-server-cloud-fs";
const roots = [parseUri("s3://my-bucket")];
const provider = new S3Provider({ region: "us-east-1" });
const cache = new MemoryStore(provider, { ttlMs: 60_000, syncDebounceMs: 2000 });
const vfs = new VirtualFS(provider, cache);
await vfs.hydrate();
const server = createMcpServer({ vfs, roots });
Exported API
MCP Inspector
# Quick demo (no credentials needed)
bun run inspect:memory
# Custom configuration
bun run inspect -- s3 s3://my-bucket --region us-east-1 --enable-shell
MCP App: Interactive Shell (xterm.js)
Build the app: bun run build:app → outputs dist/app/shell-app.html.
Catppuccin Mocha theme, command history, auto-resize. Renders inside compatible MCP hosts (Claude Desktop) via the MCP Apps extension.
Development & Testing
See CONTRIBUTING.md for full setup instructions.
AI agent skills are installed separately after cloning via bun x skills add semgrep/skills — see CONTRIBUTING.md for details.
Test tiers
CI pipeline
The CI workflow runs on every push/PR:
- ci job: lint → typecheck → unit tests (with coverage) → HTTP E2E → build
- e2e job: full E2E with Docker Compose (MinIO, Redis)
HTTP E2E tests use the in-memory provider and need zero infrastructure, making them fast and reliable for every CI run.
AI Agent Skill
The skills/cloud-fs directory contains an installable AI agent skill that teaches coding assistants (Claude Code, Gemini CLI, etc.) how to use cloud-fs as a POSIX-like virtual filesystem. Install it to give your assistant fluency with cloud storage commands.
What it provides
- MCP mode auto-detection — recognizes
mcp__cloud-fs__*tools and maps user intents to the right tool calls - Bootstrap flow — walks the user through first-time setup when the MCP server isn't configured yet
- POSIX-to-MCP mapping — translates shell commands (
ls,cat,grep,find,cp, etc.) into the correct MCP tool calls - Provider credential reference — AWS, Azure, GCS, MinIO/RustFS, SQLite setup guidance
.mcp.jsonpersistence — offers to save provider configuration so future sessions are pre-wired
Installation
# Claude Code
claude mcp add-skill nogoo9/mcp-server-cloud-fs
# skills.sh
npx skills add nogoo9/mcp-server-cloud-fs
# or with bun instead
bun x skills add nogoo9/mcp-server-cloud-fs
See CONTRIBUTING.md for details on the skill system.
Documentation
Full documentation is available at nogoo9.github.io/mcp-server-cloud-fs.
- 📖 Versioned docs for each release (v0.4.0+)
- 🔄 PR preview docs for open pull requests
- 🔍 Full-text search, dark mode, responsive design
- Built with VitePress
To run the documentation site locally:
bun run docs:dev # start dev server at http://localhost:5173
bun run docs:build # build static site
bun run docs:preview # preview production build
License
PolyForm Shield 1.0.0. Free for any non-competitive use.