Virtual Filesystem

io.github.lu-zhengdaPublished by GitHub account lu-zhengdav0.2.2Updated Oct 24, 2026

PostgreSQL-backed virtual filesystem for agents: session isolation, shared stores, POSIX ops, RLS.

Overview

AI-generated overview

A PostgreSQL-backed virtual filesystem for AI agents, giving assistants persistent, session-isolated file storage with POSIX-style read, write and search tools.

What you can do
Read, write and append files, and check metadata or existence with stat, inside a virtual filesystem stored in PostgreSQL rather than the host disk.Organize storage with ls, mkdir, mv and rm, including recursive directory removal and automatic parent creation.Find files by glob pattern and search file contents by regex, backed by PostgreSQL trigram indexes.List and use named cross-session stores so data can be shared between agents or kept as long-term memory.
When to use it
Useful when an assistant needs a persistent workspace that survives process restarts, container recycling or redeployments, or when several agents should share files through named stores. Also fits sandboxed file operations where agents should not touch the host filesystem.
Requirements
Runs locally over stdio via the npm package, needing Node.js 20 or later and PostgreSQL 14 or later with the pg_trgm extension. The DATABASE_URL connection string is required; VFS_AUTO_INIT, VFS_SESSION_ID and VFS_ENABLE_RLS are optional. Optional RLS setup requires running SQL scripts and a dedicated database role.
Before you install
DATABASE_URL is a secret connection string containing database credentials; keep it out of shared configs. The tools write, move and recursively delete data in the database, so mistakes affect stored files. VFS_AUTO_INIT creates tables automatically, and enabling RLS requires manual schema and role changes. Data lives in your PostgreSQL instance, not a third-party service.

Installation

In SourceWeft

  1. Open Virtual Filesystem in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

mcp-virtual-fs

[npm version] [CI] [npm downloads] [License: MIT] [Node.js]

An MCP server that provides AI agents with a persistent, PostgreSQL-backed virtual filesystem. Supports session-isolated file operations, cross-session shared stores, glob/grep search, and Row Level Security — all exposed as standard Model Context Protocol tools.

Works with any MCP client: Claude Desktop, Claude Code, Cursor, Windsurf, Cline, and others.

Features

  • Persistent file storage — files are stored in PostgreSQL and survive process restarts, container recycling, and redeployments
  • Session isolation — each agent session gets its own namespace automatically, no configuration needed
  • Cross-session stores — named persistent stores for sharing data between agents or for long-term agent memory
  • 11 POSIX-style tools — read, write, append, stat, ls, mkdir, rm, mv, glob, grep, stores
  • Glob and grep search — find files by pattern (**/*.ts) or search content by regex, powered by PostgreSQL trigram indexes
  • Row Level Security — optional database-enforced isolation between sessions for multi-tenant deployments
  • Zero config — auto-creates tables on first run with VFS_AUTO_INIT=true

Use Cases

  • Agent scratchpad — give LLM agents a persistent workspace to read/write files across tool calls
  • Long-term agent memory — store notes, context, and knowledge across sessions using named stores
  • Multi-agent collaboration — multiple agents share files through cross-session stores
  • Sandboxed file operations — agents interact with a virtual filesystem instead of the host OS
  • CI/CD artifact storage — persist build outputs, logs, and reports in a queryable filesystem

Why

Agents work well with filesystems for context management, but coupling storage to the agent runtime means data is lost when pods restart or containers are recycled. This MCP server decouples storage from runtime by moving file operations to PostgreSQL — giving agents persistent, isolated, and searchable file storage without touching the host filesystem.

Prerequisites

  • Node.js 20 or later
  • PostgreSQL 14 or later (with pg_trgm extension — included in most distributions)

Quick Start

1. Set up PostgreSQL

bash
# Using Dockerdocker run -d --name vfs-postgres \  -e POSTGRES_DB=vfs \  -e POSTGRES_PASSWORD=postgres \  -p 5432:5432 \  postgres:16-alpine

2. Configure your MCP client

Add to your MCP client config (e.g., Claude Desktop claude_desktop_config.json or Claude Code .mcp.json):

json
{  "mcpServers": {    "virtual-fs": {      "command": "npx",      "args": ["-y", "mcp-virtual-fs"],      "env": {        "DATABASE_URL": "postgresql://postgres:postgres@localhost:5432/vfs",        "VFS_AUTO_INIT": "true"      }    }  }}

That's it. VFS_AUTO_INIT=true creates the tables on first run.

3. Use the tools

Tool names are short POSIX-style names:

write({ path: "/notes/todo.md", content: "# My Tasks\n- Ship feature" })read({ path: "/notes/todo.md" })ls({ path: "/notes" })glob({ pattern: "**/*.md" })grep({ pattern: "TODO" })

All tools return structured JSON responses.

Tools

ToolParametersReturnsDescription
readpath{content, size}Read file contents
writepath, content{path, size, has_parents}Write file (creates parents automatically)
appendpath, content{path, appended_bytes}Append to file (creates if missing)
statpath{exists, type?, size?, children?}Check existence and get metadata
lspath{entries: [{name, type}]}List directory (dirs first, then alphabetical)
mkdirpath{path, already_existed}Create directory and parents (mkdir -p)
rmpath{path, deleted}Remove file or directory recursively
mvsource, destination{source, destination}Move/rename file or directory
globpattern{files, count}Find files by glob (e.g., **/*.ts, **/*.{js,ts})
greppattern, path_filter?{matches, count}Search file contents by regex
stores(none){stores, count}List all persistent store names

All tools (except stores) accept an optional store parameter for cross-session persistent storage.

Session Management

Sessions are handled automatically — no session ID in tool parameters.

How it works:

TransportSession identityBehavior
stdioAuto-generated UUID per processEach MCP connection = unique session
HTTP/SSETransport-provided sessionIdMCP protocol handles it
AnyVFS_SESSION_ID env varDeterministic/resumable sessions

Priority: transport sessionId > VFS_SESSION_ID env var > auto-generated UUID.

Resumable sessions

To resume a previous session across process restarts, set a deterministic session ID:

json
{  "env": {    "DATABASE_URL": "postgresql://...",    "VFS_SESSION_ID": "my-agent-session-1"  }}

Cross-Session Stores

Named stores persist across sessions. Any session can read/write to a store by passing the store parameter:

// Session A writes to a storewrite({ path: "/context.md", content: "project notes", store: "agent-memory" })
// Session B (days later) reads from the same storeread({ path: "/context.md", store: "agent-memory" })
// Without `store`, operations target the session's own namespacewrite({ path: "/scratch.txt", content: "session-only data" })
// List all available storesstores()

Stores are auto-created on first use.

Environment Variables

VariableRequiredDefaultDescription
DATABASE_URLYes—PostgreSQL connection string
VFS_AUTO_INITNofalseAuto-create tables on startup
VFS_SESSION_IDNorandom UUIDDeterministic session ID
VFS_ENABLE_RLSNofalseEnable Row Level Security
VFS_STORAGE_BACKENDNopostgresStorage backend type

Manual Database Setup

If you prefer to manage the schema yourself instead of using VFS_AUTO_INIT:

bash
psql $DATABASE_URL -f sql/schema.sql

Row Level Security (optional)

RLS provides database-enforced session isolation. Even if application code has a bug that omits a WHERE session_id = clause, PostgreSQL itself prevents cross-session access.

bash
# Run after schema.sqlpsql $DATABASE_URL -f sql/rls.sql
# Update the vfs_app passwordpsql $DATABASE_URL -c "ALTER ROLE vfs_app PASSWORD 'your-secure-password'"

Then configure the MCP server to connect as vfs_app:

json
{  "env": {    "DATABASE_URL": "postgresql://vfs_app:your-secure-password@localhost:5432/vfs",    "VFS_ENABLE_RLS": "true"  }}

Development

Requirements

  • Node.js 20+
  • Docker (for integration tests — runs PostgreSQL via testcontainers)
bash
git clone https://github.com/lu-zhengda/mcp-virtual-fs.gitcd mcp-virtual-fsnpm installnpm run build

Commands

CommandDescription
npm run buildCompile TypeScript
npm testRun all tests (requires Docker)
npm run test:unitRun unit tests only
npm run test:integrationRun integration tests only
npm run lintRun ESLint
npm run lint:fixAuto-fix lint issues
npm run devRun with tsx (no build step)

Testing

Tests use testcontainers to spin up real PostgreSQL instances in Docker. No mocks — the integration tests exercise actual SQL queries, trigram indexes, and RLS policies.

bash
# Requires Docker runningnpm test

Session Cleanup

Ephemeral sessions can be cleaned up periodically:

sql
DELETE FROM vfs_sessionsWHERE is_persistent = false  AND created_at < now() - interval '7 days';

The ON DELETE CASCADE on vfs_nodes handles file cleanup automatically. Persistent stores (created via the store parameter) are never affected.

License

MIT

Source: README.md at commit cfc45ed

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v0.2.2LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts