mcp-memory-bucket
v0.12.5
Published
MCP server exposing skill_* (reusable coding patterns) and memory_* (point-in-time working context) tools over a markdown+frontmatter source, cached into SQLite at runtime.
Downloads
2,212
Readme
mcp-memory-bucket
MCP server exposing skill_* (reusable coding patterns, stored as
agentskills.io-standard SKILL.md folders) and
memory_* (point-in-time working context — plans, specs, SQL, session
summaries) tools over markdown+frontmatter files, cached into SQLite at
runtime.
See AGENTS.md for the frontmatter schemas, tool reference,
and how an agent should use this — the same content is also published as
the memory-bucket-authoring skill
(src/skills/builtin/memory-bucket-authoring/SKILL.md), built in so it's
always available regardless of --memory-dir/cwd, fetchable via
skill_get("memory-bucket-authoring") from any MCP session connected to
this server. See
skill-bucket-v0-plan.md at the workspace
root for the full design plan.
Example uses
A few illustrative scenarios (not transcripts of real sessions):
Saving a reusable pattern as a skill. After pairing on a Lit dropdown
component with keyboard navigation and ARIA roles, you tell the agent
"save this as a skill for next time." It calls skill_create with a
description covering both what the pattern does and when to use it, so
future sessions can discover it by keyword.
Capturing a plan before a big refactor. Before starting a multi-day
migration, you ask the agent to write out its plan and save it under the
ticket key: memory_create(key: "RMXS-142", doc_type: "plan", ...). Later
sessions on the same ticket call memory_get("RMXS-142") to pick up
exactly where the last one left off, without you re-explaining context.
Triaging a year-old bucket. A memory bucket that's accumulated docs
for a year has a lot of dead weight. Sorting the web UI by "Oldest first"
surfaces the stalest entries; selecting a batch and clicking "Mark
deprecated" flags them without losing their original status, and a
follow-up "Delete" (after a confirm dialog) clears out the ones nobody
needs. The same triage works from an agent via memory_bulk_update(ids,
{ deprecated: true }) followed by memory_bulk_delete.
Bulk-tagging after a search. "Find every skill about deploys and mark
the outdated ones deprecated" becomes skill_search("deploy") to find
candidates, then skill_bulk_update(names, { deprecated: true }) to flag
the stale ones in one call — no need to touch each file individually.
Run
Via npx
No install needed — runs the published package directly:
npx mcp-memory-bucket
# or, with the flags described below:
npx mcp-memory-bucket --memory-dir /path/to/dirThis is the simplest way to point an MCP client at a memory bucket without cloning this repo.
From source
npm install
npm run build
npm start # or: npm run dev for auto-restart on source changesStarts a stateless StreamableHTTP MCP server at http://localhost:8767/mcp
(override with PORT). This is a long-lived process, not a one-shot CLI —
the SQLite cache is kept current by a file watcher for as long as the
server runs.
How the cache stays fresh
The cache is a single SQLite file, .memory-bucket-cache.sqlite, written
next to memory-bucket.config.json in the base directory (cwd by default,
or MEMORY_BUCKET_DIR/--memory-dir — see Configuration below). It's a
scan cache, not the source of truth — the markdown files on disk always
are, and the cache can be safely deleted; it's rebuilt on next startup.
- On startup, every configured folder is fully walked and each file is upserted into the cache, keyed by mtime — a file whose mtime hasn't changed since it was last cached is skipped, so restarting is cheap even with a large folder.
- While running, each folder is watched (via
chokidar) foradd,change, andunlinkevents on matching files, and the cache is updated incrementally as they happen — no polling, no manual reindex. OnlySKILL.mdfiles count for skill folders; any.mdfile counts for memory folders. The watcher only looks 10 directories deep. A rename arrives as a delete-then-add, not a single rename event. - Adding a folder (via the web UI, or a
skill_sources/memory_sourcesentry present at startup) triggers a scan of just that folder, not a full rescan of every folder already cached. - Removing a folder (via the web UI) drops its rows from the cache and search index immediately — it never touches files on disk.
The same process also serves a browser UI at http://localhost:8767/ for
searching/filtering skills and memory docs by tag, folder, status, owner,
deprecated flag, and fulltext (SQLite FTS5), and sorting by creation date
or last-touched — a way to review and clean up what's in the index
without going through an agent. It also manages folders: add a skill or
memory folder by browsing the filesystem, or remove one (unregisters it and
drops its cached rows — never deletes files on disk). Beyond browsing,
the UI supports marking entries deprecated (independent of status,
so you don't lose "shipped"/"active" context when flagging something
stale) and deleting entries — both single-item and multi-select bulk,
with a confirm dialog before any delete. Deeper edits (renaming, editing
body content, changing tags) still go through the skill_*/memory_*
tools or the files directly. From an MCP session connected to this
server, call bucket_open_ui to get the URL. If no folders are configured
yet, the UI opens straight into a first-run "add your first folder" screen.
The UI is a Lit + avosignals app built with Vite (src/client/,
bundled to dist/client/) — npm run build builds it (along with the
server); npm start does not rebuild it, so run npm run build
again after changing anything under src/client/. npm run dev rebuilds
the client on change alongside the server, for active UI development.
The 🗂 Folder View toggle switches the same UI into a directory-style
browsing mode, for exploring what's in the bucket by structure instead of
narrowing a flat list. A dropdown picks between three layouts — Folder
tree (the default: expand a folder to see its items), Breadcrumb
drill-down (folder cards you click into, one level deep), and Tag →
Name (flat and cross-folder: items group by tag regardless of which
folder they're in, so browsing by tag isn't scoped to one folder; an item
with multiple tags appears under every one of them, Gmail-label style, and
each leaf shows which folder it's actually in; untagged items land in an
"(untagged)" bucket). The last-picked mode and each mode's expand/collapse
state persist across reloads. Folder View keeps its own folder/tag
selection and its own open item, entirely independent of the flat Filters
view's activeFolders/activeTags/selection — switching between the two
never disturbs either one's state. The broader query scope (search text,
type filter, date range, deprecated/paused visibility) is shared between
both views. Clicking a folder or tag node opens a resizable middle pane
listing its contents; clicking an item there, or clicking a leaf item
directly in the tree, opens it in the detail pane on the right.
Configuration
By default the server uses the current working directory as the base for memory/skill sources. Override that with one of:
{
"skill_sources": ["./skills"],
"memory_sources": ["./docs"]
}Paths are resolved relative to the working directory. If no
skill_sources/memory_sources key is present, each defaults to the
example above only when that directory already exists on disk;
otherwise the server starts with zero folders and the UI's first-run
screen offers to add one.
Multiple folders (e.g. a personal skills folder plus a shared company repo) are supported — give each source a name instead of a bare path:
{
"skill_sources": [
{ "name": "personal", "path": "~/skills" },
{ "name": "company", "path": "../company-repo/skills" }
]
}Bare-string and {name, path} entries can be mixed in the same array.
With a single folder of a kind, skill_create/memory_create/etc. work
exactly as before. Once 2+ folders exist, those tools require an explicit
folder argument (and skill_list/memory_list gain an optional folder
filter) — every list/get response also includes which folder each item
came from. Folders can be added or removed at runtime through the web UI
without a restart; adding one there also appends it to this config file.
the
MEMORY_BUCKET_DIRenvironment variable, or the--memory-dir <path>CLI flag — either overrides the base directory that the (still-defaultable)skill_sources/memory_sourcesare resolved against.npm start -- --memory-dir /path/to/other/dir # or: MEMORY_BUCKET_DIR=/path/to/other/dir npm startNote the
--before--memory-dir— without it, npm swallows the flag itself instead of passing it through to the script.the
FOLDERFOO_MODEenvironment variable, or the--folderfoo-mode <off|dev|cloud>CLI flag — controls whether the web UI integrates with folderfoo (remote skill/memory folders backed by a folderfoo server, plus thefolderfoo-profile-circlelogin widget). Defaults tooff: no folderfoo code loads, no login widget appears, no network calls to any folderfoo server are made. Set todevto point at a local folderfoo dev server (http://localhost:3000, e.g. viafolderfoo/start-dev.sh), orcloudfor the real hosted deployment (https://files.cuul.cc).npm start -- --folderfoo-mode dev # or: FOLDERFOO_MODE=dev npm startUnlike browser-only folderfoo consumers (mindfoo, bulletino, avotuner), which infer dev-vs-prod from
window.location.hostname, mcp-memory-bucket is a CLI tool whose own page is alwayslocalhostregardless of which folderfoo deployment (if any) is wanted — hence the explicit flag instead of hostname-sniffing.
Test
npm test