/mongodb/.
For connection setup, see MongoDB Setup.
Install the extra:
Config
Fields marked secret are redacted in snapshots.
VFS.md
The VFS.md an agent reads with MongoDB mounted at/<path>.
- Rendered
- Raw
cluster → database → collection / view
model. The database directory always appears in the path, even when
databases filters to a single entry.
documents.jsonl
One JSON object per line, encoded with BSON Relaxed Extended JSON. BSON-specific types round-trip through their canonical$ wrappers:
cat / head / tail / grep / jq can read this file through the same
streaming interface. The cursor fetches documents in batches; head can stop
after a prefix. Commands that need the whole input, such as sort or jq -s,
can still buffer it. Use bounded reads when exploring a large collection.
Because the file is rendered on demand, stat / ls -l report no size and
du returns 0 for it (computing the real size would require rendering the
whole collection). Use wc -c documents.jsonl for the actual rendered byte
count, or wc -l documents.jsonl for an exact document count (which can scan
the collection). stat -c %s prints - for an unknown size and 0 only for
a known empty file. Missing dates also display as -.
Long directory listings include a total row. GNU ls reports allocated disk
blocks there; the VFS does not expose allocation metadata, so Mirage prints
total ? for nonempty listings and total 0 for empty listings. This is an
intentional divergence from GNU output, not a sum of rendered file sizes.
stat checks existence and type without counting documents, sampling fields,
or fetching indexes. This keeps ls, find, and opening a stream independent
of the collection size. The same unknown-size convention applies to Postgres
row exports and other rendered VFS files.
schema.json
Generated from the first 100 documents in_id order. Includes:
- field path → observed BSON type frequencies (nested paths unioned across the sample)
- index definitions from
listIndexes, without volatile access counters - the
$jsonSchemavalidator if one is registered
$indexStats, so reading a schema cannot
change its own content. Views skip indexes.
database.json
Lists collection and view names using two catalog listings, without a per-collection count. Useful forcat /mongodb/<db>/database.json to get an overview
without recursing into each entity.
Elided fields
Fields listed underelide_fields are dropped entirely from
documents.jsonl output. The type stays documented in schema.json, so
heavy fields (embeddings, large binary, raw text blobs) can be hidden
from agent reads without losing the schema signal:
cat (one-shot
streaming reads) and tail -f (live change-stream follows).
Streaming and Limits
cat, grep, head, and tail -f consume documents lazily through a
batched PyMongo async cursor (or change stream); the consumer cancels to stop
fetching. Direct output is capped at 2,000 lines by default, with a truncation
notice on stderr. Pipes and redirects bypass this output cap. See
command output limits to change the bound.
Smart Commands
grep and rg
For one plain text in a collection’s or view’sdocuments.jsonl, grep and
rg ask MongoDB for the documents that may hold it, in the _id order a plain
read takes, and search their lines instead of the whole collection. The
filter matches the text in any case against every key and string of a
document, eight levels deep; a document nested deeper, or holding a value it
cannot look into (binary, a regex, code), is always sent. MongoDB still scans
the collection, but only those documents are sent. The file is read as usual
when the text holds anything but ASCII letters and spaces, or could match an
Extended JSON key ($oid, $date, $numberLong), a JSON literal (true,
null) or an id (a word of hex letters only, such as ada). schema.json
and database.json are always read, and -m stops the cursor early.
head / tail / tail -f
tail uses server-side sort + limit. A count past max_doc_limit on
a collection that long is refused with File too large rather than
printing fewer lines than asked. head streams in _id order and stops
after the count. tail -f on a collection reads the last lines at one
snapshot, then opens a Mongo change stream of the inserts after it and
yields each new document as a JSONL line in the same format as cat; on a
view it polls.
See Lines:
tail -f follows inserts on a replica set on MongoDB 5.0 or later, for
the snapshot read and the change stream; Atlas already satisfies this. On
a server outside a replica set it polls, and so does a view, which has no
change stream.
Cache
The MongoDB VFS lists database names, collection names, and document counts. These listings are not cached by default (index_ttl = 0); a workspace or
mount index: caches them for its ttl.
Document content is not cached. The VFS leaves caches_reads
at its default of False, so cat, grep, head, and tail always
query the live collection
instead of serving a stored snapshot. This keeps reads consistent with a
mutable database and ensures tail -f follows the live change stream
rather than replaying cached bytes.
Integration
What MongoDB answers through its own API, so fewer files are read. Integration explains each command.Example
Runnable examples
Three working examples live underexamples/python/vfs/mongodb/:
mongodb.py— agent-shell workflow:ls,tree,cat,head,tail,wc,stat,grep/rgat every scope,jq,find,cd+ relative paths.mongodb_vfs.py— in-process VFS:os.listdirandopen()walk every readdir level (root, database,collections/,views/, entity) and readdatabase.json,schema.json,documents.jsonl(collection + view).mongodb_fuse.py— same coverage as the VFS example, but the tree is mounted as a real filesystem so other processes cancat/ls/headthe mountpoint directly.
mirage_test database seeded by scripts/seed_mongodb_test.py.
Finding IDs
_id is serialized as {"$oid": "..."} under Extended JSON:
Working with Large Collections
Streaming is the default; reach for these patterns when you want to keep the round trip small:elide_fields;
schema.json still documents the original type so the agent can decide
when to ask for the raw bytes through a different path.