Yggdrasil
Yggdrasil is a local-first, persistent memory server for AI coding agents that allows you to store, search, and recall decisions, lessons, and project context across sessions and tools. It is 100% local and private, requiring no cloud interaction or API keys by default.
ygg_health— Check engine health: verify the memory engine is running, see total memory count, and confirm whether semantic (vector) search is available.ygg_recall— Search across all projects to find prior solutions, decisions, and lessons — ideal for "have I solved something like this before?" queries.ygg_bootstrap— Prime your working context by loading the top durable memories for a specific project (decisions, conventions, lessons, status), ranked by usage and pinned items.ygg_search— Perform targeted free-text search within a single project's memory, with optional filtering by memory type (decision, lesson, fix, convention, etc.).ygg_remember— Save a single atomic fact (decision, fix, lesson, convention, status, or follow-up) to a project's durable memory; near-duplicates are automatically merged and secrets are refused.ygg_materialize— Export a stored memory to an Obsidian-compatible Markdown file on disk for human reading or archiving, without modifying the stored memory.
Additional capabilities include optional semantic/cross-lingual search via local Ollama models, background consolidation and deduplication of memories, and seeding memory from Claude Code/Codex transcripts, Obsidian vaults, and Markdown files.
Allows importing memory from Obsidian vaults and exporting memory as Markdown notes compatible with Obsidian.
Every new chat, your AI forgets. You re-explain the project, the decisions, the gotchas — every time, in every tool. Yggdrasil is a tiny always-on memory that any agent plugs into. Open a new session, in any project, with any AI, and it already knows what you decided, what broke, and what's still open.
$ cd ~/projects/checkout-api && claude # a brand-new session
🌳 Yggdrasil (injected automatically at session start)
• [project_status] payments refactor: idempotency keys added; open: e2e tests
• [lesson] webhook 401 → signing secret rotated; update env + redeploy
> "have I solved a flaky websocket reconnect anywhere before?"
🌳 recall → found in project `realtime-dash`:
refresh the token *before* opening the socket, then retry with capped backoff.No "let me remind you what we did yesterday." It's just there.
🚀 Install
Two commands, inside Claude Code (the plugin launches via uv):
/plugin marketplace add VonderVuflya/Yggdrasil
/plugin install yggdrasilThe engine lazy-starts on first use and generates its own local token — no API key, no cloud, nothing to configure. Codex and Cursor use the same flow.
Host / tool | Command |
uvx (recommended CLI) |
|
npm / npx |
|
pipx |
|
pip |
|
Homebrew (macOS) |
|
Claude Desktop (app) | drag the |
from source |
|
ygg install is a one-time guided setup: it installs an always-on background service, registers the MCP tools with every agent host it finds — Claude Code, Codex, OpenCode — and, if your hardware allows, recommends optional local models (or pick none to stay zero-config).
Install OpenCode first, then run ygg install (or ygg redeploy if Yggdrasil is already set up) — the entry is written for you and merged into any existing opencode.json. Confirm with:
opencode mcp list # -> ✓ yggdrasil connectedInstalled OpenCode after Yggdrasil? Just re-run ygg install.
If you'd rather write it by hand, note that OpenCode's schema differs from Claude's in four places at once — servers live under mcp (not mcpServers), type is required, command is one array (not command + args), and env is environment (not env), so the Claude snippet won't port:
// ~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"yggdrasil": {
"type": "local",
"command": ["/path/to/python3", "~/.yggdrasil/scripts/ygg_mcp_server.py"],
"enabled": true,
"environment": { "YGG_ENGINE_URL": "http://127.0.0.1:42069" }
}
}
}No token goes in the config — the engine reads the 0600 ~/.yggdrasil/token itself. Run ygg doctor if the tools don't show up.
There is also a yggdrasil-memory skill for any Claude surface: MCP connects the tools, the skill teaches the agent when to use them. Use both for the best behavior.
Try it with nothing installed and a throwaway DB: uvx --from yggdrasil-memory ygg serve --reset --db /tmp/ygg.sqlite.
Then just work: ask your agent "recall what we decided about this project", tell it "remember this decision" — next session it's already there. Verify the install any time with ygg doctor.
Already have history? Seed memory from your existing Claude Code + Codex transcripts, Obsidian vaults, and CLAUDE.md repos — distilled locally:
ygg seed --dry-run # see what it would import; drop the flag to distill for realLeaving another memory tool? ygg import --from mcp-memory --path memory.json pulls its whole store into Yggdrasil (deduped, secret-guarded) — then you can delete it.
Related MCP server: agentmem
Why
🧠 Persistent — decisions, lessons, and project status survive across sessions.
🔌 One brain, every tool — Claude Code, Codex, OpenCode, and any MCP host share the same memory.
🌐 Cross-project recall — "this looks like what you did in project B — reuse it?"
🧹 Curated, not captured — your agent saves the few things that matter; governance dedupes and archives, never deletes.
🌱 Self-maintaining (opt-in) — a small local model consolidates memory in the background. Zero API tokens.
🪪 One identity everywhere — an optional name and persona every agent picks up, so Claude Code and Codex feel like the same assistant.
🔒 100% local — your memory lives on your machine. No cloud, no account, no telemetry.
🧠 How it works
Yggdrasil is memory + tools — the intelligence is your LLM. It just makes sure the right memory is in front of the right agent at the right moment.
🛎️ Always-on daemon — a tiny local service (~21 MB RAM) your agents reach over MCP tools (
ygg_search,ygg_recall,ygg_remember…).🪝 Hooks — session start auto-injects identity, project status, and open follow-ups (~300 tokens); an optional per-prompt hook auto-recalls memory relevant to each request.
📌 Ranking — pinned and frequently-recalled memories surface first.
🧹 Governance — duplicates and conflicts are queued for review; changes are non-destructive (archive, never delete).
📓 Obsidian — every memory doubles as a plain-Markdown note you can read, edit, and grep.
🎛️ Memory tiers — zero-config by default
Out of the box, Yggdrasil runs on SQLite + FTS5 with zero dependencies — instant keyword search, no models, nothing to download. Optional local models add two independent tiers:
Tier | You add | You gain |
0 · default | nothing — SQLite + FTS5 | keyword search, zero deps, instant — recall@1 = 0.77 |
1 · semantic | an embedding model ( | search by meaning, across languages — recall@1 = 0.94, recall@3 1.00 |
2 · self-maintaining | a small LLM ( | background dedupe/merge of memory (propose-only) |
The runtime only computes vectors and runs the background model — every memory and every vector stays in the same local SQLite.
ygg install scans for Ollama, LM Studio and llama.cpp, offers to start whichever is installed but idle, and then shows one menu per job with green for models you already have and red for models it would download. Pick a row, and it writes embed_backend, embed_url and distill_url for you — including the part nobody guesses right, that embed_url wants the /v1 base while distill_url wants the host root. A runtime on another machine is one URL: paste it and the dialect is detected. ygg recommend shows the same scan plus the full catalog without changing anything.
Embeddings (semantic search):
Model | Size | Good for |
| 45 MB | English, tiny & fast |
| 274 MB | English, better quality (768d) |
| 670 MB | English, high quality (1024d) |
| ~560 MB | multilingual (EN/RU + 50 langs, 768d) |
| 1.2 GB | multilingual, top quality (heavier) |
Embedding backend — Ollama by default. ygg install sets all of this for you
once you pick a runtime; the manual route below is for scripted setups and for
changing one thing later. To use an OpenAI-compatible /v1/embeddings server
instead (llama.cpp's llama-server --embeddings, OpenRouter, LM Studio, vLLM),
set embed_backend:
# local llama.cpp — no key needed
ygg config set embed_backend openai
ygg config set embed_url http://127.0.0.1:8080/v1
ygg config set embed_model bge-small-en-v1.5
ygg redeploy
# OpenRouter — free embeddings, no GPU needed
ygg config set embed_backend openai
ygg config set embed_url https://openrouter.ai/api/v1
ygg config set embed_model nvidia/llama-nemotron-embed-vl-1b-v2:free
ygg config set embed_api_key sk-or-... # or export YGG_EMBED_API_KEY
ygg redeployThe key is stored in ~/.yggdrasil/embed_api_key (0600) rather than
config.json, and reaches the daemon as a file path — so it never shows up
in ps, the launchd plist or the systemd unit. ygg config list masks it.
Check it took with ygg doctor — dense should name your model:
✓ dense active (nvidia/llama-nemotron-embed-vl-1b-v2:free)ygg install handles all of this. Read on only if you're wiring it by hand.
1. Two settings, two different shapes of the same URL. embed_url is the
/v1 base; distill_url is the host root. Same server, and swapping them gets
you a 404 that reads like the endpoint is simply wrong.
ygg config set embed_backend openai
ygg config set embed_url http://127.0.0.1:1234/v1
ygg config set distill_url http://127.0.0.1:12342. The model id is not what you downloaded. lms get nomic-embed-text puts
a model on disk that the API answers to as
text-embedding-nomic-embed-text-v1.5. Ask the server, don't guess:
curl -s http://127.0.0.1:1234/api/v0/models | grep '"id"'3. Turn on Just-In-Time model loading (Developer tab). Without it nothing is loaded when the daemon calls, and every request 404s.
4. Turn on "run the server on login". The Yggdrasil daemon starts at boot; if LM Studio's server doesn't, dense search silently degrades to lexical until you next open the app.
1. Use an inference key, not a provisioning key. Keys from
openrouter.ai/settings/provisioning-keys
can only mint other keys — embedding calls with one return a baffling
401 User not found. Create a normal key at
openrouter.ai/settings/keys instead.
Note that GET /api/v1/models answers 200 OK for any key, valid or not —
it ignores auth entirely, so it can't tell you whether your key works. Check
GET /api/v1/key instead: it returns is_provisioning_key, and fails outright
on a bad key.
2. Privacy settings silently hide most models. If a model 404s with
All providers have been ignored, the model is fine — your account is
filtering out every provider that serves it. Fix it at
openrouter.ai/settings/privacy.
That filter is also why openai/text-embedding-3-* can come back 403 on a
provider's terms of service.
Browse what's actually available at openrouter.ai/models?output_modalities=embeddings (26 models at the time of writing). Useful ones:
Model | Price / 1M tokens |
| $0 |
| $0.004 |
| $0.01 — multilingual |
| $0.20 |
Staying local still wins on quality and privacy: on the 232-memory / 110-query
corpus, local paraphrase-multilingual scores recall@1 0.964 vs 0.946
for the free hosted model — and your memories never leave the machine. Reach for
a hosted backend when the box can't run Ollama, not to chase accuracy.
Bigger vectors do not buy accuracy here — on the same corpus
mxbai-embed-large (1024d) scores 0.809 and nomic-embed-text (768d) 0.818,
a difference their confidence intervals swallow whole. What actually moves the
number is whether the model handles your languages: both are English-only and
collapse to 0.40–0.45 on cross-language queries, where the multilingual default
holds 0.95.
Background consolidation (small LLM):
Model | Size | Good for |
| ~400 MB | tiny, fast on CPU |
| ~1 GB | best CPU default |
| ~2 GB | better quality, slower on CPU |
The engine itself is swappable — any service meeting the MemoryBackend contract is a drop-in (YGG_ENGINE_URL); see docs/backend-boundary.md.
📊 The numbers
Measured by eval/ygg_eval.py — 232 memories, 110 labelled queries, ranking weights tuned on the dev split only, so holdout is the unbiased number (recall@1, with the paraphrase-multilingual model):
Search view | holdout recall@1 | recall@3 | zero-dep lexical |
Within a project (the real path, pool ~11) | 0.94 | 1.00 | 0.76 |
Whole store (no filter, pool 232) | 0.72 | 0.87 | 0.69 |
Within a project — the path you use — the right memory is #1 for 0.94 of queries and in the top 3 every time (recall@3 = 1.00). Searching the whole store with no filter is harder (recall@1 0.72, recall@3 0.87 across all 232). Zero-dep lexical mode already solves keyword and code-identifier queries (1.00); the local model adds meaning and cross-language (crosslingual 0.25 → 0.95). The full breakdown in BENCHMARKS.md has 95% CIs, pool sizes, and per-class scores — rerun it in a minute: python3 eval/ygg_eval.py --report.
🆚 Yggdrasil vs the rest
Everyone else either auto-captures transcripts or sells you a cloud. Yggdrasil's bet: keep the few things that matter, curated and de-duped, in plain rows you own — and share them across every tool and project.
Yggdrasil | Built-in memory (Claude Code · Codex) | mem0 / OpenMemory | |||
Curated decisions / lessons / status (not transcripts) | ✅ | ⚠️ auto-notes | ❌ captures everything | ⚠️ | ⚠️ free-form notes |
One memory across tools | ✅ | ❌ vendor-siloed | ✅ | ✅ | ✅ |
Cross-project recall ("solved this in project B") | ✅ | ❌ repo-scoped | ⚠️ | ⚠️ | ⚠️ |
100% local by default | ✅ | ✅ | ⚠️ cloud sync add-on | ❌ hosted-first | ✅ |
Zero dependencies (stdlib + SQLite) | ✅ | — | ❌ Node + Bun + worker daemon | ❌ Docker + Qdrant + LLM key | ❌ |
Works with no LLM & no API key | ✅ | ✅ | ❌ AI-compresses | ❌ | ✅ |
Semantic search, fully local | ✅ opt-in Ollama | ❌ grep-only | ⚠️ optional Chroma | ⚠️ needs API key or Docker stack | ❌ |
Plain Markdown you own (Obsidian-ready) | ✅ | ✅ | ❌ | ❌ | ✅ |
Closest neighbor — claude-mem: capture-everything memory that records and AI-compresses every session (Node 20+ and Bun, a persistent worker daemon; Chroma optional). Yggdrasil is the opposite bet: a small, high-signal store instead of a growing firehose. mem0 is an SDK plus a hosted platform for building apps that remember their users — even self-hosted it needs an LLM API key. Built-in memories are genuinely useful — and structurally siloed: one vendor, one repo, one machine, literal grep. Yggdrasil is the layer above them (and ygg seed can bootstrap itself from those same transcripts). Different layer entirely: context-mode (live context window) and Context7 (fresh library docs) — both pair fine with Yggdrasil.
🧰 Commands
Agents see six MCP tools: ygg_health, ygg_bootstrap, ygg_search, ygg_recall, ygg_remember, ygg_materialize — auto-registered by the plugin or ygg install.
Memory ops
Command | What it does |
| Cross-project search — "have I done this anywhere?" |
| Project-scoped search ( |
| Save a durable memory (secret-guarded, deduped) |
| Pull a project's memory before starting work |
| Pin a memory so it reliably surfaces |
| Link memories ( |
| Archive an outdated memory — |
| Export one memory to an Obsidian note |
| Write a curated digest into |
| Migrate another memory tool's store into Yggdrasil ( |
| Work the governance queue — consolidate duplicates, flag stale/conflicting memories (archive-only, reversible) |
| Hard-delete one memory · bulk-undo a bad seed (confirms first) |
Cold start
Command | What it does |
| Distill Claude Code + Codex transcripts, Obsidian vaults, |
| Discover + estimate only · re-distill everything |
| Nightly auto-distill (launchd) — memory keeps itself fresh; |
| Sync memory across machines through your own git repo — plain JSON files, no cloud in the loop |
| Distill one dir/file into lessons |
| Backfill missing embeddings (restores dense recall) |
Service & setup
Command | What it does |
| Guided setup · diagnose with actionable fixes · upgrade |
| Show/set persistent settings ( |
| Manage the always-on daemon |
| SessionStart hook on/off · (re)register MCP |
| Model catalog · print auth token · remove everything |
Give it a personality — edit ~/.yggdrasil/identity.json:
{ "name": "Jarvis", "persona": "concise, proactive, dry wit", "user_facts": ["prefers TypeScript", "ships small PRs"] }Heavy seeding, weak laptop? Point distillation at any box on your LAN — a desktop with Ollama, LM Studio, llama.cpp, even an iPhone running a local-LLM server app: ygg config set distill_url http://<box>:11434. Yggdrasil auto-detects the API dialect (Ollama or OpenAI-compatible); your data still never leaves your network — details in docs/ygg-cli.md.
❓ FAQ
Built-in memories are per-vendor, per-repo, per-machine, and retrieved by literal text match. Yggdrasil is the layer above: the same memory in Claude Code, Codex, and any MCP host, recall across projects, optional semantic search — still 100% local. It bridges them both ways: ygg seed distills your existing native memory + transcripts into the shared brain, and ygg export-native writes a curated digest back into AGENTS.md/MEMORY.md — so even a fresh clone or a tool without Yggdrasil still gets your curated memory.
No. The engine, the database, and the optional models all run locally. No account, no telemetry. The only outbound call is a version check against PyPI.
No — by design. Retrieval is automatic; writing is deliberate (the agent calls ygg_remember for durable lessons). Capture-everything pollutes memory and burns tokens, so we don't. The optional background model consolidates what's already saved (propose-only).
No. The default is pure lexical search — zero dependencies, instant. Semantic search is opt-in and uses a local model via Ollama. The installer recommends one that fits your hardware.
The engine idles at ~21 MB RAM (lexical default) with ~0% CPU; disk is tens of KB per memory. Session start injects ~300 tokens; each tool call returns a small snippet. All heavy work (indexing, embeddings, consolidation) runs off-LLM on your machine.
Yes. Memories materialize to Markdown notes in an Obsidian vault — read, edit, or remove them like any file. The engine never hard-deletes; it archives (reversible).
🚦 Status & roadmap
Alpha. The happy path and the governance loop are gate-tested (scripts/run_gates.sh); not yet hardened for multi-user or production use. macOS today; Linux/Windows service installers are built and in final on-device testing.
Next: 🛰️ cross-surface sync (one memory across CLI, web, and phone) · 🔗 relation graph (SOLVES / SUPERSEDES / CONTRADICTS) · 🐧 Linux/Windows GA.
🤝 Contributing
Issues and PRs welcome. Run scripts/run_gates.sh and python3 -m unittest discover -s tests before submitting — all gates must stay green.
📜 License
GNU AGPL v3.0 — see LICENSE. Free and open source: use, modify, self-host, redistribute. If you modify it or offer it as a network service, you must release your source under the same license.
Available Tools
6 toolsygg_bootstrapLoad one project's memoryARead-onlyIdempotent
Load the top durable memories for ONE project — decisions, conventions, lessons, and open status — to prime work at the start of a task. Use when you already know the project; for cross-project discovery use ygg_recall, for a targeted in-project query use ygg_search. Results are project-scoped and ranked, most-used and pinned first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of memories to return (default 5). Raise for a fuller picture; lower to keep context small. | |
| query | No | Optional focus to rank within the project, e.g. "payment retries". Leave empty for the project's most relevant memories overall. | |
| project | Yes | Project to scope to — usually the git repository name, e.g. "checkout-api". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, and non-destructive behavior; description adds that results are ranked and pinned-first, which is useful behavioral detail beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, front-loading purpose then usage guidance, with no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description specifies return content types and ordering, providing a complete picture for a simple retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters with descriptions; tool description adds no significant new meaning beyond restating project scoping and optionality of limit/query.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool loads 'top durable memories' for one project, listing content types (decisions, conventions, lessons, open status) and distinguishes from siblings ygg_recall and ygg_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises use when the project is known and provides alternative tools for cross-project discovery and targeted queries, making the appropriate context unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ygg_healthCheck memory engine healthARead-onlyIdempotent
Report the local Yggdrasil memory engine's health: running status, total stored-memory count, and whether semantic (dense-vector) search is available. Call this first when any other ygg_* tool fails unexpectedly, to confirm the engine is up before retrying. Returns a small JSON status object.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive. The description adds value by detailing the return contents (running status, stored-memory count, semantic search availability) and specifying it returns a small JSON object. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, each earning its place. The first delivers purpose and content, the second gives usage and return type. No extraneous words, front-loaded structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema, the description adequately conveys the return value (small JSON status object with specific fields). For a simple health-check tool with zero parameters, this is complete enough for an agent to understand the tool's behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, and schema description coverage is 100% (trivially). The description does not need to add parameter semantics; baseline 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool reports the local Yggdrasil memory engine's health, listing specific metrics (running status, stored-memory count, semantic search availability). The verb 'report' and resource 'health' are precise, and the tool is easily distinguished from sibling tools focused on bootstrap, materialize, recall, remember, and search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to call this tool first when other ygg_* tools fail, providing a clear, actionable use case. This guidance helps the agent decide when to invoke it, even though it does not list when not to use it, the directive is sufficient for this diagnostic tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ygg_materializeExport a memory to MarkdownAIdempotent
Write ONE stored memory to a human-readable Markdown note (Obsidian-compatible) on disk; the stored memory itself is unchanged. Use when the user wants to read, edit, or archive a specific memory as a file. Needs the memory id from a prior ygg_recall / ygg_search / ygg_bootstrap result plus its project; returns the written file path.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The memory id to export, as returned by a prior recall/search/bootstrap, e.g. "ygg_4a5c82a...". | |
| project | Yes | The project the memory belongs to. | |
| output_dir | No | Directory to write the Markdown note into (default "vault/04-learnings"). Must stay inside the local vault root; paths escaping it are rejected. | vault/04-learnings |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate idempotentHint=true, destructiveHint=false, readOnlyHint=false. The description adds context: the stored memory is unchanged, filesystem path validation (must stay inside vault), and output format compatibility. This enriches behavioral understanding beyond annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph that front-loads the core action, then adds usage context and prerequisites. Every sentence adds distinct value, and there is no redundancy or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters, no output schema, and no nested objects, the description covers the purpose, when to use, prerequisites, return value (file path), and behavioral constraints (path safety). It is fully self-contained and actionable for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds contextual meaning by specifying that 'id' must come from a prior recall/search/bootstrap result and that 'project' is required. It also mentions the default output_dir and path constraint, providing extra guidance beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool writes a single memory to a Markdown file on disk, specifying the verb (write), resource (stored memory), and output format (Obsidian-compatible Markdown). It also distinguishes from siblings by emphasizing the export-to-file action, which is not covered by ygg_recall, ygg_search, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates when to use the tool ('when the user wants to read, edit, or archive a specific memory as a file') and provides prerequisites (memory ID from prior tools, project). It implies alternatives by noting need for prior recall/search/bootstrap, but does not explicitly list when not to use or compare to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ygg_recallRecall prior work across all projectsARead-onlyIdempotent
Search durable memory ACROSS ALL projects for prior solutions, decisions, and lessons to reuse. Use BEFORE solving any non-trivial problem ("have I handled this before?"); for one known project use ygg_bootstrap to load its context or ygg_search for a targeted query instead. Ranks by relevance and past usage — lexical by default, semantic when embeddings are enabled.
| Name | Required | Description | Default |
|---|---|---|---|
| json | No | Return raw JSON instead of formatted text (default false). Set true to parse fields programmatically. | |
| type | No | Optional filter to one memory category. Omit to recall across all types. | |
| limit | No | Maximum number of memories to return (default 5). | |
| query | Yes | Natural-language description of the problem or topic to find prior work for, e.g. "token refresh before opening socket". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint. Description adds ranking behavior (relevance and past usage, lexical vs semantic). No contradictions, but could detail more about ranking mechanics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action. Every sentence provides distinct value (purpose, usage guidance, ranking note). No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, when to use, alternatives, and ranking. No output schema exists, but description doesn't explain return format. However, for a search tool, this is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters with descriptions. Description provides context for the query and mentions memory categories but doesn't add significant meaning beyond schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states the tool searches durable memory across all projects for prior solutions, decisions, and lessons. The verb 'search' and resource 'durable memory' are specific, and it distinguishes from siblings like ygg_bootstrap and ygg_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear guidance: 'Use BEFORE solving any non-trivial problem' and explicitly gives alternatives for other scenarios (ygg_bootstrap for one project, ygg_search for targeted query).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ygg_rememberSave a durable memoryA
Persist ONE atomic, reusable fact (a decision, lesson, fix, convention, or status) to a project's durable memory for future sessions. Call right after you decide something, learn a lesson, or fix a non-obvious bug; store one idea per call, phrased to stand alone. Near-duplicates are merged automatically and obvious secrets (API keys, tokens) are refused. Returns the saved memory id.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Memory category that best fits the fact. | |
| solves | No | Optional id of a memory this one SOLVES (e.g. this fix resolves that open follow_up) — links them in the relation graph. | |
| source | No | Provenance tag for where this memory came from (default "ygg-mcp"). Usually leave as default. | ygg-mcp |
| content | Yes | The single durable fact — one atomic idea, phrased so it stays useful with no surrounding context. | |
| project | Yes | Project this fact belongs to — usually the git repo name, e.g. "checkout-api". | |
| confidence | No | Optional confidence 0.0–1.0; higher ranks the memory more strongly in recall. Defaults to the engine's standard for tool writes. | |
| supersedes | No | Optional id of a memory this one REPLACES — records a SUPERSEDES edge and archives the old memory (reversible). | |
| contradicts | No | Optional id of a memory this one CONTRADICTS — both stay active, the dispute is recorded for review. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate a write operation (readOnlyHint=false, destructiveHint=false). The description adds key behaviors: near-duplicates are merged automatically, obvious secrets are refused, and it returns a saved memory id. These details go beyond the annotations, providing useful expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences, front-loaded with the core action, then usage timing, then behaviors, then return value. No wasted words. Every sentence adds value, and the structure is logical and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 8 parameters (3 required) and no output schema, the description covers purpose, usage, param semantics, and behavioral traits. It doesn't detail return format beyond 'id', but that is sufficient for a save operation. It lacks rate limits or error handling, but annotations and schema provide no such info. Overall, it is complete enough for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaning by explaining that 'content' should be one atomic idea phrased standalone, and that 'solves', 'supersedes', and 'contradicts' create relationships. It also clarifies 'type' enum values as categories and 'source' typically left default. This enriches the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs ('persist', 'store') and a clear resource ('durable memory'). It states exactly what the tool does: save one atomic fact. The title 'Save a durable memory' reinforces this, and the description distinguishes from sibling tools like ygg_recall (retrieve) and ygg_search (search).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: 'Call right after you decide something, learn a lesson, or fix a non-obvious bug.' It also instructs to store one idea per call. However, it does not explicitly state when not to use or name alternatives, though the context of sibling tools implies retrieval tools for reading.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ygg_searchSearch one project's memoryARead-onlyIdempotent
Search ONE project's durable memory with a free-text query and optional type filter — the precise, in-project lookup. Use when you know the project and want specific matches (e.g. every 'fix' about auth); for cross-project discovery use ygg_recall, to load a project's whole context use ygg_bootstrap. Lexical BM25 plus semantic ranking when embeddings are enabled.
| Name | Required | Description | Default |
|---|---|---|---|
| json | No | Return raw JSON instead of formatted text (default false). Set true to parse fields programmatically. | |
| type | No | Optional filter to one memory category. Omit to search all types. | |
| limit | No | Maximum results to return (default 5). | |
| query | Yes | Free-text query describing what you're looking for, e.g. "flaky e2e tests". | |
| project | Yes | Project to search within — typically the git repo name, e.g. "webdesk". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint. Description adds that it uses 'Lexical BM25 plus semantic ranking when embeddings are enabled', which is beyond annotations and helps understand behavior. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is 3-4 sentences, front-loaded with the core action, then usage guidance, then technical detail. No fluff, every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the main aspects: scope (one project), query, type filter, alternative tools, and algorithm. No output schema exists, but description doesn't explain return format (though schema has a json parameter for raw output). Almost complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with good descriptions. The description mentions 'free-text query and optional type filter' but adds little extra beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches ONE project's durable memory with free-text query and optional type filter. It uses specific verb-search and resource-project memory, and differentiates from siblings like ygg_recall and ygg_bootstrap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use when you know the project and want specific matches'. Provides alternatives for cross-project (ygg_recall) and whole context (ygg_bootstrap). No ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose, with descriptions explicitly contrasting use cases (e.g., ygg_bootstrap vs ygg_recall vs ygg_search). No overlap or ambiguity.
All tools follow a consistent 'ygg_<verb>' pattern with lowercase verbs, making the naming uniform and predictable.
With 6 tools, the surface is well-scoped for a durable memory system, covering core operations (store, retrieve, search) and auxiliary tasks (health, materialize) without bloat.
The tool set provides a complete lifecycle for memory management across projects: persistence, cross-project and in-project retrieval, context loading, health monitoring, and file export. No obvious gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Portable memory for AI agents: capture once, recall across Claude, Cursor, and any MCP client.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Persistent, inspectable memory for AI agents with lineage, correction, and a hosted MCP endpoint.
Private persistent memory for Claude, ChatGPT & Gemini via MCP - semantic search, zero-code setup.
Related MCP Servers
AlicenseAqualityFmaintenanceAn MCP server that integrates with mem0.ai to help users store, retrieve, and search coding preferences for more consistent programming practices.29658Apache 2.0- AlicenseAqualityDmaintenanceGoverned memory for coding agents with trust lifecycle, conflict detection, staleness tracking, and health scoring. SQLite + FTS5, zero infrastructure. Works with Claude Code, Cursor, Codex, Windsurf.133MIT
- FlicenseNot gradedqualityBmaintenanceLocal-first cross-agent memory for AI coding agents. Persistent, shared memory over MCP — what you tell one agent can be recalled by another — with all data stored in a single local SQLite file, no cloud and no API keys.
- AlicenseAqualityAmaintenanceLocal-first memory for Claude Code and any MCP client: hybrid vector + keyword search and a bi-temporal knowledge graph in one SQLite file. Local embeddings, no API key, $0/token.512061PolyForm Noncommercial 1.0.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/VonderVuflya/Yggdrasil'
If you have feedback or need assistance with the MCP directory API, please join our Discord server