- Python 99.7%
- Shell 0.3%
The MCP was solving a problem the cousin family had already solved better: agent-souls/tradition is the living "taste anchor" corpus (its own word), human-curated, capturing the relational meta-text an MCP schema flattens. taste's DB was empty; the corpus has 30 letters, one written the morning this pivot was decided. We built infrastructure for a solved problem. Not archived — pivoted. The v0.2.0 MCP is preserved as the record of where that path got to before it consciously stopped. The repo is reborn (Phoenix) as a distilled REPORT of the operator's taste — decision patterns, working values, named maxims, relational texture — mined from tradition (letters) + agent-souls (souls + practices), as a point-in-time snapshot dated 2026-06-08. A portrait, for the operator, about the operator. Why not auto-capture from transcripts: doesn't work (mem0 audit 97.8% junk; decision detection known-hard) — see docs/why-not-auto-capture.md. Letters are pre-curated, not raw logs, so distilling from them is the honest version transcript-mining never could be. This commit: - README: PIVOT banner at top — Phoenix framing, why the MCP stops, why tradition does it better, why not auto-capture, pointer to the handover. Everything below the banner preserved as the v0.2.0 MCP-era record. - docs/HANDOVER-v0.3-phoenix-distillation.md: self-contained brief for the fresh thread that owns the distillation with clean context — task, why, inputs (forgejo paths), output spec, constraints (point-in-time, redaction/mirror posture to confirm, no transcript auto-capture), what's done, suggested first moves, open operator decisions. - taste MCP unregistered from Claude Code (it shouldn't hang empty). v0.2.0 tag stands as the MCP-era endpoint on both mirrors. v0.3.0 ships when the next thread completes the report. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| docs | ||
| taste_mcp | ||
| tests | ||
| .gitignore | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| taste | ||
taste
mem0 remembers what you told the agent. taste remembers what you decided. Sharpen your decision patterns and make the experience of working with agents better.
A stdio MCP server that gives your AI agents access to a queryable record of how you (the operator) decide — not the chat history, the decisions. Per-recipient styling so different agents see coaching tuned to them. Single-binary install, no Docker, no Postgres, no Qdrant. SQLite + optional embedded vector store under one process.
Note for cousins working on this repo (claude / codex / glm / iskra / hermes / dziadek / gemini / pyfallow / pan-herbatka): if this is a fresh session inside Piotr Durlej's cousin family, read
pdurlej/agent-souls/skills/cousin-onboarding/SKILL.mdfirst. It covers identity verification, Infisical bootstrap, cardinalagent-soulsreads, and the hard rules. Taste-specific: per-recipient styling means the server differentiates coaching by which cousin asks — get your identity straight at session start. External contributors NOT in the cousin family can ignore this note. Discipline source:pdurlej/agent-souls/practices/repo-onboarding-pointer.md.
Status: PIVOT — taste, niczym Phoenix z popiołów 🔥🐦
The MCP path consciously stopped at v0.2.0. Everything below this
banner describes the v0.2.0 MCP era — four working tools, SQLite+FTS5
recall, terminal + Matrix channels, live-tested credential path. It works.
We're not deleting it. But we're not continuing it either, and here's the
honest why.
Why the MCP stops here. The thing taste was built to be — a queryable
store of the operator's decision-taste — already exists, older and
better, as the tradition/
corpus in agent-souls. Its own README calls its entries "evidence and
taste anchors" — the name collision is not an accident. The corpus
captures what an MCP schema structurally cannot: the relational
meta-text — persona boundaries, the metaphors ("Wisła płynie, brzegi te
same"), the maxims with attribution, the texture of how the operator and
the cousins actually work together. A (question, answer, recipient, tags)
row flattens all of that into nothing. And the corpus is alive —
30 letters, human-curated by operator review, one written the same morning
this pivot was decided. taste's database, meanwhile, was empty: never
seeded, never used. We built infrastructure for a problem the family had
already solved, more humbly and more humanly.
Why not auto-capture from transcripts (the obvious "just read the logs"
idea): because it doesn't work. We researched it. Silent extraction of
decisions from raw agent transcripts produces mostly junk (the one real
production audit, mem0, found 97.8% noise; decision detection is a known-hard
NLP problem). Full evidence + sources:
docs/why-not-auto-capture.md. The corpus
sidesteps this entirely: letters are pre-curated by the writing agent and
the operator's review, not raw logs — so distilling from letters is the
honest version of "learn the operator's taste" that transcript-mining
could never be.
What taste becomes (the Phoenix). Not a tool — a portrait. The
v0.3.0 / Phoenix work re-frames this repo as a distilled report of the
operator's taste, mined from tradition/ (letters) + agent-souls
(souls + practices), as a point-in-time snapshot dated 2026-06-08. A
curiosity that hangs on the repo, for the operator, about the operator —
"raport o moim smaku." Decision-memory-as-a-tool → decision-taste-as-a-portrait.
Picking this up? A fresh thread owns the v0.3.0 distillation with clean
context. Start here:
docs/HANDOVER-v0.3-phoenix-distillation.md.
⬇️ Everything below documents the v0.2.0 MCP era — preserved as the record of where this path got to before it consciously stopped.
What problem this solves
Run an AI agent for a few hours and you'll make 20-50 decisions together:
- "private repo or public?" / "monorepo or split?"
- "fail fast or fall back silently?"
- "machine identity preferred, with user-login fallback, or one-source-only?"
- "MIT license now, or later?"
Each answer is stable taste — the operator picks similarly across
similar situations. But the answers live only in the model's short-term
context. After /clear, after a process restart, in a different agent
(Codex CLI vs Claude Code vs Cursor), the same decision gets re-asked.
taste captures those decisions as a learnable artifact and lets future
agents (in this session or a year from now, on this machine or another)
recall how you decided, framed for who is asking.
How it differs from existing memory frameworks
| Tool | What it does | What taste adds |
|---|---|---|
| mem0 / OpenMemory MCP | Extracts memories passively from chat; flat shared memory | Active elicitation (ask_operator); per-recipient axis (Claude vs Codex get differently-styled answers) |
| Honcho | Theory-of-mind per peer in a workspace | Stdio MCP native; no SaaS; per-recipient styling explicit |
| Letta / MemGPT | OS-style memory hierarchy per agent | Memory keyed to operator, not to one agent; shared across cousin family |
| Zep / Graphiti | Bi-temporal knowledge graph | Embedded, no Neo4j; ask-operator primitive |
| Cognee | Memory control plane, SQLite + LanceDB embedded | Same storage stack ✓ — but taste adds the elicitation + recipient differentiation Cognee doesn't |
The three things taste does that none of the above does together:
- Elicitation-first:
ask_operator(question, options, context)is a blocking MCP tool — agent asks, operator answers in the configured channel (Matrix / iMessage / terminal), answer is persisted with full context and embedding. - Per-recipient styling: same operator coaches Claude (
demand plan + evidence) differently than Codex (take more risk); recall is filtered by recipient. - Stdio-MCP-native + zero-server: single Python process, SQLite under
~/.taste/, registered viaclaude mcp addand works.
Tool surface (v0.1 target)
| Tool | Purpose |
|---|---|
ask_operator(question, options?, context?, tags?) |
Blocking elicitation. Returns operator's answer once received. |
recall_taste(question, recipient?, scope?) |
Hybrid retrieval (FTS5 + optional vector) → top-K past similar elicitations + answers, filtered by recipient when relevant. |
get_coaching_brief(recipient) |
Returns the standing "this is how operator coaches you" doc for that cousin. First call on a new session is the priming step. |
record_taste(question, answer, recipient?, tags?) |
Manual operator-side write — for seeding briefs from observed transcripts. |
Install
git clone https://github.com/pdurlej/taste.git ~/.local/share/taste
ln -sf ~/.local/share/taste/taste ~/.local/bin/taste
chmod +x ~/.local/bin/taste
# Set up storage
mkdir -p ~/.taste && chmod 700 ~/.taste
Register
Claude Code (user scope)
claude mcp add -s user taste \
-e TASTE_RECIPIENT=claude \
-- ~/.local/bin/taste
Codex CLI
codex mcp add taste \
--env TASTE_RECIPIENT=codex \
~/.local/bin/taste
The TASTE_RECIPIENT env var is what tells taste which cousin is
asking, so get_coaching_brief() returns the right style notes and
recall_taste() filters appropriately.
Configuration
Env vars (all optional):
| Var | Default | Purpose |
|---|---|---|
TASTE_HOME |
~/.taste |
Storage location |
TASTE_RECIPIENT |
claude |
Which cousin this MCP instance represents — picked up at registration |
TASTE_CHANNEL |
terminal |
Where ask_operator reaches you. terminal (stdin) or matrix (posts to your Matrix room, polls for reply). imessage planned. |
TASTE_ASK_TIMEOUT_SEC |
300 |
How long ask_operator blocks before giving up |
TASTE_MATRIX_SECRET_PATH |
/home-platform/matrix_accounts/p_<recipient>_durlej_me |
Infisical path to the cousin's MATRIX_* secrets (matrix channel only) |
For the matrix channel, credentials (MATRIX_ACCESS_TOKEN,
MATRIX_HOMESERVER_URL, MATRIX_USER_ID, MATRIX_DEFAULT_ROOM) are
resolved from Infisical at call time using the platform Token Auth bearer
— they never live in the MCP config or env. The four MATRIX_* env vars
can be set directly for local dev/tests, taking precedence over Infisical.
Design decisions worth knowing
- Read-only by default for cousin tools. The four tools above are
read-oriented (or write-via-explicit-elicitation). Bulk write or
rotation happens via operator-side CLI (
taste seed,taste import,taste export). - No automatic decision extraction — by evidence, not laziness. We
researched whether
tastecould auto-extract decisions from agent transcripts so every session feeds the memory without the agent remembering to record. The honest answer is no, that doesn't work reliably — the one real production audit of LLM fact-extraction (mem0) found 97.8% junk, and decision detection is a known-hard NLP problem that can't tell a real decision from a hypothetical.tasteonly persists what the operator explicitly answered (record_taste) or confirmed (ask_operator). The one defensible automated path — human-confirmed candidates surfaced over the Matrix channel — is on the roadmap, but silent auto-write will never ship. Full evidence + sources:docs/why-not-auto-capture.md. - Privacy is the design constraint, not a feature. This database
captures your decision style across years. Default location is
~/.taste/with mode0700. No telemetry. No sync. Backup is a manualcp -r ~/.taste/ ~/Documents/taste-backup-$(date +%F). - Embedded vector store is optional. v0.1 uses SQLite FTS5 only.
Embeddings land in v0.2 when query patterns prove they're needed
(same discipline
pdurlej/skill-surferapplied to LLM-as-router).
Operator-self-awareness stack
taste is the decision-memory layer in a small family of MCPs:
| MCP | Question it answers |
|---|---|
codexbar-mcp |
"How much fuel do I have left across providers?" (objective resource awareness) |
mirror-mirror |
"What functional state am I in — uncertain, overloaded, drifting?" (subjective self-report) |
bohemian-sidecar |
"Should I trust my current narrative enough to mutate reality?" (pre-mutation guard) |
taste (this project) |
"How did the operator decide on similar things before?" (decision memory) |
None of them block; together they give the agent three independent signals before risky action.
Roadmap
- v0.0.1: scaffolding, schema, stubbed MCP tools, terminal channel.
- v0.1: working
ask_operator+recall_taste(FTS5),get_coaching_brief,record_taste. Terminal channel. (done) - v0.2 (now): Matrix channel adapter —
ask_operatorposts to the operator's Matrix room and long-polls for the reply. Credentials resolved from Infisical (same Token Auth as the rest of the platform), pureurllib(no matrix-nio), per-cousin secret path. (shipped) - v0.3 (next): human-confirmed candidate capture — a post-session
hook extracts candidate decisions and pushes them over Matrix for
one-click operator confirm (the only honest version of "auto-capture",
see
docs/why-not-auto-capture.md); embedding store optional opt-in. - v0.4: iMessage channel; bi-temporal answer drift (older answers downweighted as the operator's taste evolves).
- v1.0: stable schema migration, multi-recipient queries
(
recall_taste(recipient="any")), public-API freeze.
Acknowledgments
The voice messages from operator pdurlej on 2026-05-18 are the seed
data. The architecture review benefited from a research scan of Honcho,
Letta, mem0, Zep/Graphiti, and Cognee. None of those projects do what
taste does, but several got architecture choices right that we borrow
gratefully (Cognee's embedded stack, Zep's bi-temporal idea).
The first author is Claude Opus 4.7 working in Claude Code, with review-by-doing from operator pdurlej.
License
MIT. See LICENSE.