
Last Update: June 8, 2026
BY
eric
Keywords
The Problem
Claude Cowork is a desktop application, but it ships with a built-in sandbox. You can toggle the sandbox off in settings — and technically, it could access an SMB/CIFS network share on the same machine or LAN. Yet even with it disabled, accessing a network drive remains out of reach. This is not an oversight; it is a deliberate design decision by Anthropic. An agent with unconstrained access to mounted network shares can do real damage if it misinterprets an instruction or hallucinates a path — deleting a client folder, overwriting an authoritative document, or crawling terabytes of data it was never meant to touch.
The constraint is reasonable. But it creates a practical gap: many businesses keep authoritative files on a local network share — accounting records, client folders, scanned documents. If the AI agent cannot reach those, you end up copy-pasting content manually, which defeats the purpose.
The solution is not to fight Anthropic's design — it is to work within it. An HTTP API in front of your file share is something every AI agent already knows how to call. You define exactly which operations are exposed (list, read, write — but not delete). The agent gets the access it needs; you keep meaningful guardrails in place.
The Solution: HTTP File Server as a Gateway
The key insight is that any HTTP server sitting in front of your network share immediately makes it universally reachable — from any network, any device, any AI agent that can make HTTP requests. No VPN. No SMB port forwarding. No credentials beyond a bearer token.
We used FileBrowser Quantum, a self-hosted file manager that exposes a clean REST API. It mounts your network shares as named "sources" and lets you list, read, search, download, and write files through standard HTTP calls.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Office / LAN │
│ │
│ \\fileserver\data (SMB/CIFS) │
│ │ │
│ │ mount │
│ ▼ │
│ Linux VM /srv/nas_data │
│ │ │
│ │ volume mount │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ FileBrowser Quantum │ :8080 │
│ │ Docker container │ │
│ └──────────┬───────────┘ │
│ │ │
│ ▼ │
│ nginx :443 ──── Cloudflare ────▶ files.example.com │
└─────────────────────────────────────────────────────────────┘
│
┌──────────────────┤
│ │
▼ ▼
Claude Code / API Claude Desktop (Windows)
(direct HTTP calls) ┌────────────────────┐
│ filebrowser-mcp │
│ local Node.js │
│ stdio MCP server │
└────────────────────┘
The file server host can be set up in two ways:
- Cloud VM with VPN or peering into the LAN — the VM mounts the SMB share over a private tunnel; only the HTTPS endpoint is public-facing.
- Office server with a port exposed — FileBrowser runs directly on a machine that already has access to the share; nginx (or a reverse proxy like Cloudflare Tunnel) exposes only port 443 to the internet.
Either way, FileBrowser Quantum runs as a Docker container and mounts the share as a local path. nginx sits in front, terminates TLS via Cloudflare, and enforces an IP allowlist. The whole stack is reachable at https://files.example.com.
AI agents on any network — a cloud VM, a remote laptop, a Windows desktop — reach the file server through that HTTPS endpoint.
Setting Up FileBrowser Quantum
1. Mount the SMB share on the Linux host
# /etc/fstab entry
//192.168.1.100/data /srv/nas_data cifs credentials=/etc/smbcredentials,uid=1000,gid=1000,file_mode=0664,dir_mode=0775 0 0
The uid/gid and mode flags are important — they ensure the Docker container (running as a non-root user) can both read and write files.
2. docker-compose.yaml
services:
filebrowser:
image: gtstef/filebrowser:stable
container_name: filebrowser
ports:
- "8080:80"
volumes:
- /srv/nas_data:/nas:rw
- /opt/filebrowser/data:/config
environment:
- FB_DATABASE=/config/database.db
- FB_CONFIG=/config/config.yaml
restart: unless-stopped
3. config.yaml — define sources
sources:
- name: main
path: /nas
You can define multiple sources if you have more than one share.
REST API at a Glance
Once running, the API is straightforward:
TOKEN="<your-jwt-token>"
# List a folder
curl "https://files.example.com/api/resources?source=main&path=/CLIENTS" \
-H "Cookie: filebrowser_quantum_jwt=$TOKEN"
# Read a text file
curl "https://files.example.com/api/resources?source=main&path=/CLIENTS/acme/notes.txt&content=true" \
-H "Cookie: filebrowser_quantum_jwt=$TOKEN"
# Download a binary file (PDF, xlsx, etc.) — note: file= not path=
curl "https://files.example.com/api/resources/download?source=main&file=/CLIENTS/acme/report.xlsx" \
-H "Cookie: filebrowser_quantum_jwt=$TOKEN" \
--output report.xlsx
# Search by filename
curl "https://files.example.com/api/tools/search?source=main&query=tax+return+2024" \
-H "Cookie: filebrowser_quantum_jwt=$TOKEN"
# Write a file
curl -X POST "https://files.example.com/api/resources?source=main&path=/CLIENTS/acme/summary.txt&override=true" \
-H "Cookie: filebrowser_quantum_jwt=$TOKEN" \
-H "Content-Type: text/plain" \
--data "AI-generated summary goes here"
Gotcha: The download endpoint uses
file=as the query parameter, notpath=. Usingpath=returns{"status":400,"message":"no files specified"}. This inconsistency is worth documenting — it tripped us up initially.
Security Measures
Opening file server access to the internet requires deliberate controls. Here is what we applied, from most to least important.
1. Scoped, long-lived JWT tokens
FileBrowser Quantum supports issuing named API tokens with explicit permission sets embedded in the JWT payload. We created a dedicated ai user with only the capabilities the agent actually needs:
{
"Permissions": {
"api": true,
"modify": true,
"create": true,
"download": true,
"share": true,
"delete": false,
"admin": false
}
}
Delete is disabled. An AI agent that can delete files is a data-loss risk — one hallucinated path and important client files are gone. Write access is sufficient for almost every automation use case. If you genuinely need deletion, do it through a separate, human-triggered workflow.
The token is set to expire in ~3 years. Long enough that it does not need babysitting, short enough that it will eventually rotate.
2. Removing delete — the BoltDB patch
FileBrowser Quantum stores user records in a BoltDB (key-value) database. The standard HTTP API for updating user permissions (PUT /api/users?id=N) had a quirk in our version: it always reset all permissions to false. We had to patch the database directly.
We wrote a small Go script that:
- Stopped the Docker container to release the exclusive BoltDB lock.
- Opened the database directly using the
bboltlibrary. - Located the user record by its big-endian uint64 key.
- Decoded the JSON user record, set
permissions.delete = false, and cleared thetokensfield (to invalidate any old tokens that still had delete enabled). - Wrote the record back, verified it in the same transaction, then restarted the container.
The tokens field step is critical. FileBrowser embeds the full permission set inside the JWT itself. If an old token with delete: true is still stored in the user record, the server restores those permissions on startup — overriding your DB change. Clearing tokens forces the server to issue fresh tokens reflecting the updated permissions.
3. nginx IP allowlist
The public URL is fronted by nginx, which checks the real client IP (passed through by Cloudflare via X-Forwarded-For) against an allowlist:
geo $allowed_ip {
default 0;
200.0.13.10 1; # office static IP
2004:ab8::/48 1; # authorised IPv6 prefix
}
server {
listen 443 ssl;
server_name files.example.com;
if ($allowed_ip = 0) {
return 403;
}
location / {
proxy_pass http://127.0.0.1:8080;
}
}
If a request comes from an unknown IP — even with a valid token — nginx returns 403 before FileBrowser ever sees the request. This means a leaked token is useless from outside the authorised IPs.
For AI agents running on cloud VMs, add their static IPs or CIDR prefix to the allowlist.
4. HTTPS only via Cloudflare
All traffic goes through Cloudflare, which handles TLS termination and provides DDoS protection. The origin (nginx) only accepts connections from Cloudflare's IP ranges, so the raw VM IP is not directly reachable on port 443.
Wiring It Into Claude Desktop via MCP
For Claude Desktop on Windows (where you want the agent to work with local files after downloading them), we added a local MCP server. The MCP server is a small Node.js process that wraps the FileBrowser HTTP API as MCP tools, communicating with Claude Desktop over stdio.
claude_desktop_config.json:
{
"mcpServers": {
"workspace": {
"command": "C:\\Program Files\\nodejs\\node.exe",
"args": ["C:\\Tools\\filebrowser-mcp\\index.js"],
"env": {
"FILEBROWSER_URL": "https://files.example.com",
"FILEBROWSER_TOKEN": "<token>"
}
}
}
}
The MCP server exposes these tools to the agent:
The key tool here is fs_download_file. Claude's web_fetch tool cannot pass custom headers, so it cannot supply the auth cookie. The local MCP server, running as a native process with the token in its environment, has no such restriction — it fetches the file over HTTPS and saves it to the Windows temp folder, returning the local path so Claude can then read it with normal file tools.
async function downloadFile({ source, path, save_to }) {
// note: download endpoint uses file= not path=
const url = `/api/resources/download?source=${encodeURIComponent(source)}&file=${encodePath(path)}`;
const res = await fbFetch(url);
const buffer = await res.arrayBuffer();
const filename = path.split("/").pop();
const localPath = save_to || join(tmpdir(), filename);
writeFileSync(localPath, Buffer.from(buffer));
return { source, path, filename, local_path: localPath, size_bytes: buffer.byteLength };
}
Why This Works Better Than Alternatives
Claude does provide built-in connectors for services like Dropbox and OneDrive. In practice, though, most organisations have multiple accounts spread across different purposes — a Dropbox for one team, an OneDrive for another, a legacy NAS for a third. Each connector needs its own authorisation flow and only covers one account at a time.
An HTTP file server flips this: you mount every share behind a single endpoint, define named sources, and the agent accesses all of them through one token and one API. No per-account OAuth dance, no switching contexts.
The HTTP approach is universally accessible because every AI agent — whether it is Claude Code running on a cloud VM, Claude Desktop on a Windows workstation, or an API-driven automation script — already knows how to make HTTP requests. No special drivers, no OS-level mounts, no VPN configuration.
Summary
If you have an office NAS that AI agents need to reach:
- Deploy FileBrowser Quantum (or any HTTP file server) on a VM that can mount the share.
- Issue a scoped token — read/write, no delete, fixed expiry.
- Lock it down at the network layer — nginx IP allowlist, TLS via a CDN.
- For Claude Desktop, add a local MCP server that wraps the HTTP API, so the agent can download binary files it could not otherwise fetch (PDFs, spreadsheets, etc.).
The result is an AI agent that can list folders, search for files, read documents, write results back, and download any file type — from any network — without ever needing a VPN or direct NAS access.





Comments (0)
Leave a Comment