@nogoo9/mcp-server-cloud-fs
v0.7.0
Published
High-performance MCP server and library providing a cloud-native replacement for mcp-server-filesystem. Supports S3, Azure Blob, GCS, and SQLite with VFS cache coherence.
Maintainers
Readme
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-bucketRemote (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 3000Remote (WebSocket — Bun only)
bunx @nogoo9/mcp-server-cloud-fs s3 s3://my-bucket --transport ws --port 3000Demo (no cloud credentials needed)
bunx @nogoo9/mcp-server-cloud-fs memory mem://demo --enable-shell --seed-demoInteractive 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-fsFeatures
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-demoTransports
The server supports three MCP transports, selected via --transport:
| Transport | Flag | Runtime | Use case |
|---|---|---|---|
| STDIO | --transport stdio (default) | Bun, Node | Local npx, Claude Desktop, Claude Code |
| Streamable HTTP | --transport http | Bun ✅, Node ✅ | Remote deployment, multi-user, enterprise |
| WebSocket | --transport ws | Bun only | Low-latency bidirectional, real-time apps |
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-loggingWebSocket
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 3000Authentication & Authorization
Authentication is disabled by default and only applies to HTTP/WS transports. STDIO mode never requires auth.
Auth modes
| Mode | Flag | Description |
|---|---|---|
| none | --auth none (default) | No authentication. Suitable for local/trusted networks. |
| builtin | --auth builtin | Self-hosted OAuth 2.1 Authorization Server. The MCP server acts as both AS and RS. |
| external | --auth external | Validate bearer tokens against an external IdP (Okta, Auth0, Keycloak, Azure AD). |
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.comExternal 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.comext-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-credentialsext-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.comOAuth Scopes
When auth is enabled, tool access is controlled by granular scopes:
| Scope | Tools |
|---|---|
| cloud-fs:read | read_file, read_text_file, read_media_file, read_multiple_files, read_file_range, read_file_chunk, get_presigned_url, get_object_metadata, list_versions, get_file_schema, summarize_file |
| cloud-fs:write | write_file, edit_file, create_directory, set_object_tags, restore_version, patch_file |
| cloud-fs:delete | delete_file |
| cloud-fs:search | search_files, grep_file, grep_files, list_directory, list_directory_with_sizes, directory_tree, search_by_tag |
| cloud-fs:shell | shell |
| cloud-fs:admin | All tools + get_file_info, list_allowed_directories |
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:
| Endpoint | Purpose | Success | Failure |
|---|---|---|---|
| /healthz | Liveness — is the process alive? | 200 OK always | Process is dead |
| /readyz | Readiness — can it serve traffic? | 200 OK after VFS hydration | 503 during startup |
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 10CORS
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.comStructured 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.jsonNote: Requires the
noseconepeer dependency:npm install nosecone
CLI Reference
cloud-fs-mcp <provider> <root-uri> [root-uri...] [options]Providers
| Provider | URI format | Description |
|---|---|---|
| s3 | s3://bucket[/prefix] | AWS S3, and any S3-compatible endpoint (MinIO, RustFS, Cloudflare R2, Backblaze B2, Wasabi, LocalStack, …) |
| azure | az://container[/prefix] | Azure Blob Storage |
| gcs | gs://bucket[/prefix] | Google Cloud Storage |
| memory | mem://name | In-memory (ephemeral, for demos) |
| sqlite | sqlite://name | SQLite (persistent local) |
Options
Transport & Network
| Flag | Default | Description |
|---|---|---|
| --transport <stdio\|http\|ws> | stdio | Transport protocol |
| --port <number> | 3000 | Listen port (http/ws only) |
| --host <address> | 127.0.0.1 | Bind address (http/ws only) |
Authentication
| Flag | Default | Description |
|---|---|---|
| --auth <none\|builtin\|external> | none | Auth mode (http/ws only) |
| --auth-issuer <url> | — | OAuth issuer URL (builtin mode) |
| --auth-jwks-uri <url> | — | JWKS URI (external mode) |
| --auth-audience <string> | — | Expected token audience (external mode) |
| --auth-client-credentials | false | Enable Client Credentials ext-auth flow |
| --auth-enterprise-idp <url> | — | Enable Enterprise-Managed Authorization |
Production
| Flag | Default | Description |
|---|---|---|
| --cors-origin <origin> | — | Allowed CORS origin (repeatable) |
| --rate-limit <req/min> | 0 (off) | Rate limit per client |
| --rate-limit-burst <n> | 10 | Burst allowance |
| --request-logging | false | Enable structured JSON request logging |
| --audit-log | false | Enable tool invocation audit logging to stderr |
| --audit-log-file <path> | — | Write audit log to file (implies --audit-log) |
| --security-headers | false | Enable security headers via nosecone |
| --security-headers-config <json> | — | Inline JSON config for nosecone |
| --security-headers-config-file <path> | — | Load nosecone config from a JSON file |
Storage & Cache
| Flag | Default | Description |
|---|---|---|
| --region <region> | — | Cloud region (S3, GCS) |
| --endpoint <url> | — | Custom endpoint for S3-compatible backends |
| --cache-store <memory\|fs\|redis> | memory | Cache backend |
| --cache-ttl <seconds> | 60 | Cache TTL in seconds |
| --sync-debounce <ms> | 2000 | Write flush delay in ms |
| --cache-dir <path> | — | Directory for fs cache store |
| --no-cache | — | Bypass cache entirely (pass-through mode) |
| --gcs-endpoint <url> | — | Custom endpoint for GCS |
| --sqlite-db <path> | — | SQLite database file path |
| --ca-file <path> | — | PEM CA bundle for TLS (S3-compatible + Redis) |
Tools
| Flag | Default | Description |
|---|---|---|
| --enable-delete | false | Enable the delete_file tool |
| --enable-shell | false | Enable the shell tool |
| --enable-dlp | false | Enable DLP content sanitization (redacts PII/secrets from responses) |
| --grep-max-objects <n> | 1000 | Max objects grep_files scans per call |
| --seed-demo | false | Seed VFS with sample files for demo |
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-1S3-compatible storage
Any S3-compatible backend works via --endpoint. All use the standard AWS credential chain (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY).
| Provider | --endpoint value | Notes |
|---|---|---|
| MinIO | http://minio:9000 | Self-hosted; use --ca-file for TLS with a private CA |
| RustFS | http://rustfs:9000 | Rust-native S3-compatible store |
| LocalStack | http://localhost:4566 | Full AWS emulator for local dev and CI |
| Cloudflare R2 | https://<account-id>.r2.cloudflarestorage.com | No egress fees; use an R2 API token as the secret key |
| Backblaze B2 | https://s3.<region>.backblazeb2.com | Use B2 application key ID / key |
| Wasabi | https://s3.<region>.wasabisys.com | Compatible, no egress fees |
| DigitalOcean Spaces | https://<region>.digitaloceanspaces.com | Use a Spaces access key |
| Scaleway | https://s3.<region>.scw.cloud | Use a Scaleway access key |
| Ceph RGW | http://<rgw-host>:<port> | Enterprise self-hosted; supports all S3 APIs |
| SeaweedFS | http://<master>:8333 | High-throughput distributed FS with S3 API |
| Garage | http://<node>:3900 | Lightweight distributed S3 for homelabs |
# 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-1TLS 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-containerGoogle Cloud Storage
Uses Application Default Credentials (ADC). Set GOOGLE_APPLICATION_CREDENTIALS or run gcloud auth application-default login.
cloud-fs-mcp gcs gs://my-bucketIn-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-shellSQLite (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-shellMCP 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
| Tool | Parameters | Description |
|---|---|---|
| read_file | path | Read a file. Binary → base64; text → UTF-8. |
| read_text_file | path, head?, tail? | Read text file with optional head/tail line limits. |
| read_media_file | path | Read image/media as base64 MCP image content block. |
| read_multiple_files | paths | Read several files in parallel. |
| read_file_range ✨ | path, offset, limit | Read a 1-based line range with total line count header. |
| read_file_chunk ✨ | path, start_byte, end_byte?, encoding? | Read a byte range without downloading the entire file. Max 10MB. |
Write tools
| Tool | Parameters | Description |
|---|---|---|
| write_file | path, content | Write/overwrite a file. Flushed after debounce window. |
| edit_file | path, edits[], dryRun?, expected_etag? | Apply { oldText, newText } edits. Preview with dryRun. Optional ETag conflict detection. |
Directory tools
| Tool | Parameters | Description |
|---|---|---|
| create_directory | path | Create a directory placeholder and parent prefixes. |
| list_directory | path | List immediate children (like ls). |
| list_directory_with_sizes | path, sortBy?, limit? | List children with sizes. Sort by size or name. |
| directory_tree | path, excludePatterns? | Recursive directory tree with glob exclusions. |
Move, Copy & Delete tools
| Tool | Parameters | Description |
|---|---|---|
| move_file | source, destination | Move file. Server-side copy + delete for same-bucket. |
| copy_file ✨ | source, destination | Copy file. Server-side for same-bucket. |
| delete_file ✨ | path | Delete file. Requires --enable-delete. |
Search tools
| Tool | Parameters | Description |
|---|---|---|
| search_files | path, pattern, excludePatterns? | Glob-based object key search. |
| grep_file ✨ | path, pattern, case_insensitive? | Regex search in a single file with line numbers. |
| grep_files ✨ | path, pattern, glob?, case_insensitive?, output_mode?, max_objects? | Regex search across all objects under a path. |
Info tools
| Tool | Parameters | Description |
|---|---|---|
| get_file_info | path | File metadata: size, last-modified, content type. |
| list_allowed_directories | (none) | List configured root URIs. |
✨ = Extended tool
Cloud-native tools ☁️
| Tool | Parameters | Description |
|---|---|---|
| get_presigned_url ☁️ | path, operation?, expires_in? | Generate a temporary access URL (default: GET, 1 hour). |
| get_object_metadata ☁️ | path | Size, content type, last modified, custom metadata, and tags. |
| set_object_tags ☁️ | path, tags | Replace object tags with key-value pairs. |
| search_by_tag ☁️ | path, tags, recursive? | Find objects matching tag filters (AND logic). |
| list_versions ☁️ | path, max_results?, page_token? | Version history with timestamps, sizes, and markers. |
| restore_version ☁️ | path, version_id | Restore a previous object version (copies over current). |
☁️ = Cloud-native tool (requires provider support)
AI-native tools 🧠
| Tool | Parameters | Description |
|---|---|---|
| get_file_schema 🧠 | path | Extract structural schema: CSV column names/types/samples, JSON shape, or text line/byte counts. |
| summarize_file 🧠 | path, max_lines? | Compact head/tail preview with file size, line count, and content type. |
🧠 = AI-native tool (reduces LLM context token waste)
Macro tools 🩹
| Tool | Parameters | Description |
|---|---|---|
| patch_file 🩹 | path, patch, format?, expected_etag? | Apply unified diffs or line-range replacements atomically in a single tool call. |
🩹 = Macro tool (combines read + transform + write)
Shell tool ⚡
| Tool | Parameters | Description |
|---|---|---|
| shell ⚡ | command | Execute POSIX-like commands. Supports pipes, redirects. Requires --enable-shell. |
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) │
└─────────────────────────────────────────────────────────┘| Operation | Resolution |
|---|---|
| get() | Cache hit → return. Tombstoned → throw. Else → provider fallback. |
| stat() | Inode overlay → cached content size → provider headObject. |
| list() | Provider listing – tombstones + overlay dirIndex entries. |
| put() | Cache set + markDirty + inode update + dirIndex. Immediate visibility. |
| remove() | Provider deleteObject + cache evict + tombstone. Immediate invisibility. |
VFS metadata is persisted to the CacheStore under __vfs__/* keys. On startup, VirtualFS.hydrate() restores state; corrupted data is silently discarded.
Caching
| Backend | Flag | Notes |
|---|---|---|
| Memory (default) | --cache-store memory | In-process, fast, not shared, not persistent. |
| Filesystem | --cache-store fs --cache-dir <path> | Survives restarts. |
| Redis | --cache-store redis | Shared, persistent. Requires ioredis peer dep. REDIS_URL env var. Use rediss:// for TLS. |
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.pemFor 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-bucketProgrammatic 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
| Export | Description |
|---|---|
| createMcpServer(ctx) | Create a configured MCP server instance |
| executeShell(command, ctx) | Run POSIX-like commands against the VFS |
| VirtualFS | FUSE-inspired write-back overlay |
| MemoryStore, FilesystemStore, createRedisStore, PassThroughCache | Cache backends |
| S3Provider, AzureProvider, GcsProvider, MemoryProvider, SqliteProvider, MultiProvider | Storage providers |
| CloudError, CloudErrorCode | Structured cloud-aware error handling |
| checkHealth, formatHealthReport | Connection health-check utilities |
| AuditLogger, StderrAuditSink, FileAuditSink | Tool invocation audit logging |
| parseUri, toCacheKey, resolveToolPath | Path utilities |
| ShellContext, ShellCommandHandler | Shell extension types |
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-shellMCP 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
| Tier | Command | Infra? |
|---|---|---|
| Unit | bun run test | No |
| E2E (HTTP) | bun run test:e2e:http | No |
| E2E (Infra) | bun run test:e2e:infra | Docker |
| Integration | bun run test:integration | Docker |
| All | bun run test:all | Docker |
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-fsSee 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 buildLicense
PolyForm Shield 1.0.0. Free for any non-competitive use.
