Install
$ agentstack add mcp-mikhail-za-tastebud-memory ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
👅 tastebud-memory
Compositional project fingerprints for AI agent memory. Give every project a deterministic high-dimensional identity vector. Every day's work becomes a weighted blend of those vectors. One "taste" (a dot product) decomposes any day back into its exact ingredients, enumerates every day a project ever touched, and detects ingredients nobody has named yet.
Zero dependencies. Two JSON files. ~600 lines of Node.
What it looks like
$ node tastebud.mjs decode 2026-01-12 # un-mix one day from its 4096-dim vector alone
2026-01-12 - Dosing pump driver; recipe-site deploy; soil sensors moved to bed 2
recovered from vector alone (vs actual):
aquarium-controller est=0.502 actual=0.500
recipe-site est=0.296 actual=0.300
garden-sensors est=0.191 actual=0.200
$ node tastebud.mjs gaps # what's been worked on but never documented?
workstreams in logs with NO project file:
aquarium-controller 4 day(s) mass=2.150 first=2026-01-10
home-lab 3 day(s) mass=1.550 first=2026-01-05
sourdough-lab 2 day(s) mass=0.900 first=2026-01-15 [NOT EVEN IN CODEBOOK]
$ node tastebud.mjs tasteslike sourdough-lab # the unknown ingredient: what is it close to?
sourdough-lab [UNKNOWN INGREDIENT - not in codebook]
keeps company with (rarity-weighted co-occurrence):
recipe-site 0.463
aquarium-controller 0.201
$ node tastebud.mjs unknowns # triage: which unknowns are RIPE to decide on?
unknowns: 1 total (decide 1, maturing 0)
sourdough-lab open 155d 2 day(s) mass=0.900 [OVERDUE ] -> alias->recipe-site
Those last two are the headline feature. sourdough-lab doesn't exist anywhere as a project: the nightly tagger invented the slug because nothing in the codebook fit, and the system flagged it and placed it next to its nearest relative. Your agent notices new workstreams forming before you've named them and then helps you decide what to do about each one. The -> alias->recipe-site is a recommendation, not a decision: sourdough-lab keeps company almost entirely with recipe-site, so the system reads it as the same work and suggests folding it in. You stay in charge: you could mint it as its own project instead, dismiss it, or wait.
The pipeline
daily log (markdown)
│ nightly LLM tagger (rules + your codebook; invents slugs when nothing fits)
▼
composition row {"date":"2026-01-12","major":[{"slug":"aquarium-controller","w":0.5},...]}
│ deterministic: slug string → seeded ±1 hypervector, day = weighted sum
▼
fingerprint (4096-dim)
│
├─ decode / where / first / cooccur / window / diff / gaps (exact membership queries)
├─ similar / drift / tasteslike / backtest (vector-layer extras)
├─ unknowns / mint / alias / dismiss / watch / autofile (ripen-then-decide triage loop)
└─ MCP server → your agent tastes before it reads
The idea (and where it came from)
This started as a question about hexadecimal colors: what if every project had a unique color, and a day's work blended them into a new color you could un-mix? The problem is that color can't do that. Three channels can't carry the membership of 50 projects, which is why mixed paint can't be un-mixed.
The metaphor that actually works is a chef's palate. A trained chef tastes an unfamiliar dish and names every ingredient in it, estimates the proportions, and (the key move) notices when there's something in the dish he doesn't recognize. That's what this does, with ~30-year-old math: hyperdimensional computing (Kanerva) / vector symbolic architectures.
- Each project slug deterministically seeds a 4,096-dimension ±1 vector. Random
high-dimensional vectors are nearly orthogonal, so they don't interfere.
- A day's fingerprint is the weighted sum of its projects' vectors.
- Decoding is a dot product against the codebook: projects in the blend score close to
their weight, and absent projects score close to zero. Mixing is reversible, the thing color couldn't do.
- The residual, the mass the codebook can't explain, is the unknown ingredient detector.
When your agent starts working on something that has no name yet, this notices before you do.
Why bother? (what semantic search can't do)
We baselined an agent's real memory (92 days, ~400 files) with embedding search before building this. Semantic search was good at date lookups and well-named topics, and structurally incapable of:
- Enumeration: "list ALL days that touched project X" (search returns representatives, never
the complete set)
- Origin under aliasing: "when did X start, including under its old name?" (recency and
volume bury the origin; this was a total miss in our baseline)
- Temporal set-difference: "active in March, dead by June"
- Absence: "which workstreams never got documentation?" (you can't embed a negation)
One concrete failure from that baseline, because it's instructive. A business project had been renamed early in its life, and we asked search "when did this start, including under its earlier name?" with three increasingly charitable query phrasings. Every one returned the later, high-volume era of the project; the actual origin date and rename event never surfaced, because similarity ranking structurally favors where the bulk of the writing is, and origins are by definition thin. tastebud.mjs first answers it exactly, because the codebook records the alias and the composition table records the date. Absence queries fail even worse: asked "which workstreams never got a project file," embedding search matched the literal phrase "project file" to documentation about the memory system itself. It cannot reason about what isn't there.
Fingerprints answer all four exactly, in milliseconds, because composition is recorded, not inferred. Tastebud complements semantic search (meaning); it doesn't replace it (membership).
The unknown-ingredient loop (detect, ripen, decide, reverse)
Detecting an unnamed workstream is only half the job. The other half is deciding what it is, without being nagged about every fleeting one-off and without making a single irreversible mistake. Tastebud closes that loop with a full triage + reversible-decision system. The chef keeps tasting; you only get asked once a dish is worth a verdict.
Detection is continuous but silent. Every night the sweeper notices new unknown slugs and logs them. No pings. A brand-new slug seen once is not a reason to interrupt you.
Mature before asking. An unknown is not surfaced for a decision until it ripens: it has to recur across days, accumulate real major weight, or age past about a week. Thin one-offs sit quietly in a Maturing bucket and never nag. A workstream that shows up for one afternoon and vanishes was noise; a workstream that keeps coming back has earned a question. All the thresholds are env-tunable (TASTEBUD_RIPE_DAYS, TASTEBUD_RIPE_MASS, TASTEBUD_RIPE_AGE_DAYS, and more).
Auto-file the obvious. If an unknown already has a project file on disk (config projectsDir), the nightly sweeper files it into the codebook automatically. A file means a human already judged it a real project, so there is nothing to ask. Logged, not pinged.
Weekly digest decides only ripe items. Once a week a review surfaces only the ripe unknowns, each with a recommendation (mint / alias / dismiss / watch) plus the context behind it, pushed through the config notifyCommand. Everything still maturing stays out of your way.
Every decision is reversible. Triage state lives in a persistent ledger (/unknowns-ledger.json). Nothing you decide is permanent:
- dismiss means "not now," not "never." A dismissed one-off revives if it starts growing
again, and comes back recommended as something to watch.
- mint writes the slug into the codebook, and is fully undoable with
mint --undo. - watch parks it on a watchlist: out of the decide queue, still in view.
- alias folds a name into an existing project and resolves it. The engine treats codebook
aliases as known, so the unknown leaves the list for good (until you remove the alias).
$ node tastebud.mjs unknowns # what is ripe to decide on right now?
unknowns: 1 total (decide 1, maturing 0)
sourdough-lab open 155d 2 day(s) mass=0.900 [OVERDUE ] -> alias->recipe-site
$ node tastebud.mjs alias sourdough-lab recipe-site # fold it in; it now resolves
$ node tastebud.mjs watch sourdough-lab "keep an eye on it" # or defer the call
$ node tastebud.mjs mint sourdough-lab --class product # or make it its own project
$ node tastebud.mjs mint sourdough-lab --undo # changed your mind: undo it
The recommendation is a hint, never a decision. Here sourdough-lab co-occurs almost entirely with recipe-site, so the system suggests aliasing it; a human who knows it is a distinct effort can mint it instead. The point of the loop is that you make the call, late enough to be sure, and can always take it back.
Quickstart (60 seconds)
git clone https://github.com/Mikhail-Za/tastebud-memory && cd tastebud-memory
node tastebud.mjs check # validate the sample data
node tastebud.mjs decode 2026-01-12 # un-mix one day from its vector alone
node tastebud.mjs where aquarium-controller # every day that project ever touched
node tastebud.mjs gaps # workstreams with no documentation
node tastebud.mjs tasteslike sourdough-lab # an UNKNOWN ingredient: what is it close to?
node tastebud.mjs backtest aquarium-controller # would the detector have caught this project emerging?
node tastebud.mjs unknowns # the triage queue: which unknowns are ripe to decide?
node tastebud.mjs color 2026-01-12 # the original metaphor, as garnish
The unknown-ingredient loop adds its own small command set (all reversible, all snapshot before they write):
node tastebud.mjs unknowns --write # write unknowns-report.md (Decide / Watching / Maturing)
node tastebud.mjs alias sourdough-lab recipe-site # fold a name into a project; it now resolves
node tastebud.mjs mint sourdough-lab --class product # promote an unknown to its own codebook slug
node tastebud.mjs mint sourdough-lab --undo # reverse a mint
node tastebud.mjs dismiss sourdough-lab "one-off" # "not now"; revives if it grows again
node tastebud.mjs watch sourdough-lab # park on the watchlist, out of the decide queue
node tastebud.mjs decisions # the persistent decision ledger, grouped by status
node tastebud.mjs digest # the daily report: ripe decide queue + recent decisions (push via notifyCommand)
node tastebud.mjs autofile # dry-run filing unknowns that already have a project file
The sample data is a fictional fortnight that includes an emerging project and an unknown ingredient, so every command above demonstrates something real.
Using it on your own memory
- Codebook: list your projects in
codebook.json(slug + aliases +has_file). Slugs are
permanent (they seed the vectors); add aliases instead of renaming.
- Backfill: have a strong LLM read each daily log and emit
{major:[{slug,w}], minor:[], new:[]}
per day (rules in examples/nightly-prompt.md). Verify a sample before trusting it. See docs/methodology.md for the gate/backtest protocol we used.
- Nightly: schedule your platform's LLM to tag yesterday into
inbox/.json
(prompt template provided), and run node tagger.mjs nightly --write an hour later as the deterministic sweeper. If the primary fails, a local model takes over and you get an alert with the reason (notifyCommand in config can point at Slack, ntfy, a webhook, anything). The same nightly pass logs new unknown slugs silently and auto-files any that already have a project file (config projectsDir); it does not interrupt you for either.
- Weekly decision loop: once a week run
node tastebud.mjs unknowns --writeand review only
the ripe unknowns, each with a recommendation. Decide with mint / alias / dismiss / watch; every call is reversible and snapshots before it writes. See [docs/production-pattern.md](docs/production-pattern.md) for the wiring.
- Agent integration: register
mcp-server/server.mjs(standard MCP, stdio) so your agent
can taste before reading: decode a day in milliseconds, then fetch only the logs that matter.
What this is not
- Not a summarizer. A fingerprint is an index, not the content. The chef recovers the
ingredient list, not the recipe steps. Taste, identify, then fetch.
- Not magic capacity. A bundle reliably holds a few dozen constituents at D=4096. Plenty
for a day, wrong for a year; aggregate windows instead.
- Not a replacement for the codebook. Decoding requires reference vectors, like a palate
requires training. Unknown ingredients are detected as unexplained mass, then triaged.
Honest engineering notes
The full methodology, including the kill-gates this project had to pass before going live, is in [docs/methodology.md](docs/methodology.md). Highlights: an adversarial verification pass re-derived 31 of 92 days blind and found 2 real tagging errors (93.5% faithful); backtests flagged emerging projects within 0-2 days; and our honest finding that the composition table does most of the query work. The vector layer earns its keep on decode, drift, similarity, and fixed-size encoding, not on basic lookups. Production wiring (primary LLM cron + deterministic sweeper + alerted local fallback) is in [docs/production-pattern.md](docs/production-pattern.md).
License
MIT. Built by Mikhail Zaidi with Claude (Anthropic), June 2026.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Mikhail-Za
- Source: Mikhail-Za/tastebud-memory
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.