WikiMoth MCP Server
Connects to an Obsidian vault of [[wikilink]] notes for deterministic multi-hop retrieval, browsing, and context management.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@WikiMoth MCP ServerFollow links from [[Onboarding]] to find the team's communication tool."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
WikiMoth
Connects the dots. The same way, every time.
wikimoth.com · pip install wikimoth
Deterministic, token-minimal, auditable memory for Claude and agents. Point WikiMoth at a
folder of [[wikilink]] notes (an Obsidian vault, or Claude's own memory folder) and it
follows the authored links to the answer flat search can't reach, shows you the exact note-chain
behind it, and feeds the reader ~99% fewer tokens than pasting the whole vault. Pure markdown,
no GPU, no vector DB, no LLM in the retrieval loop.
pip install wikimoth
wikimoth demo # instant multi-hop recall over a bundled demo vault (no setup)Already have a [[wikilink]] vault (an Obsidian vault, a notes folder)? Point WikiMoth at it and get the full connect-the-dots view in one command, no capture, no waiting:
wikimoth serve --vault /path/to/your/vault # browse + "what memory fed this answer"
wikimoth recall --vault /path/to/your/vault "a connect-the-dots question"Want it to build memory from your Claude Code sessions? Install the capture hooks; each session you run and close is written into a [[wikilink]] vault:
wikimoth install # capture: turn your Claude Code sessions into a [[wikilink]] vault
wikimoth serve # once you have captured sessions, browse themWhy not just let Claude manage its own context?
We benchmarked exactly that. An agent that browses the notes folder and prunes its own context reaches the same answers, multi-hop included (12/12 in our run). It just pays for it: 4 to 6 model round-trips and roughly 10x the billed tokens per question, because it re-sends a growing transcript every step. WikiMoth retrieves the same note-chain in one deterministic pass, no model in the loop, and shows you the exact notes behind the answer.
Real run, Claude Sonnet 4.6, 12 multi-hop questions on a reproducible vault. The ~10x counts a
reader on both sides; it is corpus-specific, not a universal law. Reproduce it with
python scripts/run_agentic_benchmark.py. Full breakdown in Honest limits.
Related MCP server: md-mcp
Why WikiMoth
Most agent memory is either paste the whole notes folder into context (expensive, and the model
gets lost in the middle) or LLM-summarised similarity search (lossy, and non-deterministic:
the same question can return different memory next week). WikiMoth takes a different bet: your notes
are the store (plain markdown), the graph is authored (your [[wikilinks]], no embeddings
to train or drift), and retrieval is code, not a model, so it's reproducible and you can read
exactly why each note was chosen.
WikiMoth | BM25 | Vector RAG | claude-mem | LLM Wiki (Karpathy) | |
Connects the dots (multi-hop over authored | ✅ | ❌ | ❌ | ❌ | ✅ (agentic) |
Deterministic retrieval (same query → same result) | ✅ | ✅ | ✅ | ❌ | ❌ |
No LLM call to retrieve | ✅ | ✅ | ✅ | ~ | ❌ |
Auditable note-chain (which notes produced the answer) | ✅ | ~ | ❌ | ❌ | ~ |
Direct-lookup recall@8 (real vault) | 1.00 | 1.00 | 1.00 | ~ | ~ |
No GPU / no vector DB / no index build | ✅ | ✅ | ❌ | ~ | ✅ |
Plain-markdown store (open in any editor) | ✅ | ~ | ❌ | ❌ | ✅ |
Token-minimal vs dumping the vault | ✅ −99% | ✅ −99% | ✅ −99% | ✅ | ~ |
Deterministic, API-free auto-capture | ✅ | ❌ | ❌ | ❌ | ❌ |
Hygiene without an LLM (conflicts · dupes · stale · supersede) | ✅ | ❌ | ❌ | ~ | ❌ |
LLM Wiki follows links and skips the vector DB like WikiMoth, but an LLM writes and reads the wiki, so retrieval is agentic (an LLM call per recall, not reproducible), while its curated pages are richer. ~ = partial / not independently benchmarked.
The edge is the combination, not higher recall: WikiMoth matches flat search on the basics and adds connect-the-dots + determinism + an audit trail + a plain-markdown store. See Honest limits for exactly where it ties and where it wins.
Compared to Karpathy's LLM Wiki
WikiMoth shares the substrate Andrej Karpathy's LLM Wiki pattern popularised: plain-markdown
[[wikilink]] notes, no vector DB, but flips the engine. In the LLM-Wiki pattern an LLM
writes and reads the wiki: rich, source-cited pages, but recall is agentic (it costs an LLM
call and the path isn't reproducible). WikiMoth computes the edges in code and retrieves with a
fixed algorithm, no LLM in the loop → the same note-chain every time, reproducible and
auditable. They're complementary, not competing: point WikiMoth at a Karpathy-style wiki and you get
deterministic multi-hop retrieval over it. (We don't claim to be "better" than the LLM Wiki: it
curates richer pages; we retrieve deterministically.)
Quickstart (read)
from wikimoth import MemoryRAG, EchoReader
rag = MemoryRAG(reader=EchoReader()) # API-free default reader
rag.index("/path/to/your/wikilink/vault") # notes → ~400-token chunks, graph built
chunks, tokens = rag.retrieve("a connect-the-dots question?", top_k=8)
print(f"{len(chunks)} chunks, {tokens} tokens to feed the reader") # the headline win
# EchoReader is a deterministic stub for wiring/tests: it prints a diagnostic
# `[echo] ...` line, NOT a natural-language answer. Swap in ClaudeReader (below)
# for real prose. The retrieval + token numbers above are the same either way.
print(rag.answer("a connect-the-dots question?"))Swap in a real Claude answer (only touches the API when constructed):
from wikimoth import MemoryRAG, ClaudeReader
rag = MemoryRAG(reader=ClaudeReader(model="claude-sonnet-4-6")) # needs ANTHROPIC_API_KEYSee what memory fed an answer: wikimoth serve
wikimoth serve # serves http://127.0.0.1:8765 (local-only)
wikimoth serve --vault PATH --port 8080A zero-dependency local web viewer (pure stdlib, no Flask, no JS framework, no network):
browse + search your notes,
the authored
[[wikilink]]graph (the same edges the retriever walks),and the one that matters, "what memory fed this answer": type a question and see the exact note-chain WikiMoth would feed a reader, with per-chunk hop distance, token counts, and the
−N%vs dumping the whole vault. Retrieval only: no LLM call, no API key, deterministic.
Because the store is plain markdown, you can equally open the same vault in Obsidian or VS Code; the viewer is a convenience, not a lock-in.
In the agent loop: wikimoth mcp
wikimoth serve is for you. The MCP server is for the model: it exposes the same deterministic
retrieval over the Model Context Protocol, so Claude calls it itself instead of you fetching context
by hand.
# 1. install into the Python that runs your Claude Code
python -m pip install wikimoth
# 2. verify the command resolves (prints status, then exits)
python -m wikimoth status
# 3. register the MCP server with Claude Code
claude mcp add wikimoth -- python -m wikimoth mcpStep 2 is the check that matters: if python -m wikimoth status prints a status line, then
python -m wikimoth mcp will run for Claude too. Use the same python in all three steps (it is
python3 on some systems); that is the one thing that has to match.
Prefer the Node world, or no Python set up? One line, no toolchain matching:
claude mcp add wikimoth -- npx -y wikimoth-mcpThe wikimoth-mcp launcher finds a Python that has
WikiMoth (or uvx-installs one on the fly), injects the vault path so the server never reads an
empty folder from the client's working directory, and passes the MCP channel through untouched. The
same npx -y wikimoth-mcp works as the server command in any mcpServers config (Claude Desktop,
Cursor, Windsurf); set WIKIMOTH_VAULT to your vault.
Now Claude has a recall(query) tool. Ask it something that lives in your notes and it calls
recall; WikiMoth walks the [[links]] and hands back the exact note-chain (no LLM call to
retrieve, token-minimal, the same result every time), and Claude answers from it. A status tool
reports the connected vault. For any other MCP client, use python -m wikimoth mcp as the server
command (stdio transport); point it at a specific vault with --vault PATH.
python -m wikimoth mcp is the portable form (it runs wherever the package is installed). The bare
wikimoth mcp works too when the console script is on your PATH. It is pure stdlib: a hand-rolled
JSON-RPC 2.0 stdio server, no MCP SDK dependency.
mcp-name: io.github.juliangeymonat-jpg/wikimoth
Capture: sessions → notes (the write half)
Retrieval needs a [[wikilink]] vault; hand-authoring one is the friction. wikimoth.capture builds
it automatically by installing Claude Code lifecycle hooks that turn each session into one
deterministic markdown note.
The invariant that matters: a note's [[wikilinks]] (the graph edges) are computed by code
(string/path matching), never by a model. An LLM may optionally draft the summary prose
(WIKIMOTH_LLM_PROSE=1), but any [[...]] it emits is stripped, never parsed as an edge. So the
graph is reproducible (same session + vault → same edges) and auditable. Default capture is fully
deterministic and makes zero API calls.
wikimoth install # writes 5 hooks into ./.claude/settings.json (absolute interpreter path)
wikimoth install --user # ~/.claude/settings.json instead
wikimoth install --vault PATH # choose where notes go (sets WIKIMOTH_VAULT)
wikimoth status # vault, note/session/buffer counts, hook state
wikimoth uninstall # remove the hooks againLifecycle: SessionStart recalls recent sessions into context · UserPromptSubmit / PostToolUse buffer the session · Stop / SessionEnd write one note. The captured notes are exactly what the read pipeline indexes; capture and retrieval close the loop.
Keep memory honest: the hygiene suite
A memory that only grows rots. Notes go stale, two notes start disagreeing, the same fact gets saved twice, an old fact is replaced but never retired. Other agent-memory tools resolve this with an LLM that silently overwrites the old state. WikiMoth ships six commands that surface it deterministically, and never delete anything: git is your audit trail.
command | finds | writes? |
| two notes asserting a different value for the same fact (type-aware, valid-time precision) | no |
| broken links, orphans, stubs, stale notes, supersession cycles | no |
| exact + near-duplicate notes (MinHash + LSH, confirmed by exact Jaccard) | no |
| notes going cold: old, rarely linked, rarely recalled (a review queue, never auto-delete) | no |
| what your memory asserted on a past date (bitemporal time-travel, no DB) | no |
| retire a fact: invalidate, don't delete | yes |
Three principles hold across all of them:
Invalidate, don't delete.
supersedemarks a note superseded and links it to its replacement in frontmatter. The old body drops out of retrieval, but its[[link]]to the current note stays live, so a query that lands on the stale note hops free to the new one. Nothing is everrm'd; the history lives in git.The tool never guesses. Every command emits candidates. The one judgement that isn't mechanical, deciding whether two notes truly contradict, is left to the calling model, never baked into the tool. So the output is reproducible and you can read exactly why each candidate was flagged.
Bitemporal, no database.
recall --as-of 2026-01-01replays what the vault asserted on that date from frontmatter validity windows alone. No event log, no vector store, no migration.
Same invariants as the rest of WikiMoth: pure stdlib, deterministic (byte-identical output),
read-only except the single supersede writer, plain markdown you can diff. The seven commands are
also exposed over MCP (list_conflicts, list_lint, list_duplicates, list_fading, supersede,
plus recall gaining as_of / show_superseded), so the agent can keep its own memory clean.
Install
WikiMoth's core is pure stdlib (dependencies = []): the retrieval engine, chunker, wikilink
graph, pipeline and capture are all vendored under wikimoth/: nothing extra to install, no GPU, no
vector DB.
pip install wikimoth
# optional extras:
pip install "wikimoth[hybrid]" # optional BM25-seeded retriever variant
pip install "wikimoth[claude,tokens]" # real Claude reader + exact tiktoken countsExtras: hybrid = BM25-seeded retriever (rank_bm25) · claude = the anthropic reader ·
tokens = exact token counts (tiktoken) · dense = the dense benchmark baseline · headroom =
reversible CCR compaction.
How it works
retrieve → compact → read. index() splits each note into ~400-token chunks (~50 overlap),
keeping per-chunk note identity so the [[wikilink]] graph still connects across chunks (multi-hop
at chunk granularity). GraphRetriever(source="wikilinks") seeds lexically, then walks the authored
links, so a passage not lexically similar to the question but reachable by a link still gets
pulled. An optional compaction stage (reversible CCR via
chopratejas/headroom) shrinks passages further before
the (paid) reader; it degrades to a no-op if headroom isn't installed.
A pure-navigation hub (a table-of-contents like MEMORY.md) can be indexed as graph edges only
(exclude_content, default ("MEMORY.md",)): its [[links]] build edges and it stays a BFS
waypoint, but its own chunks never reach the reader.
Every stage is constructor-injectable via MemoryRAG(retriever=…, compactor=…, reader=…), so you can
swap the retriever (e.g. the BM25-seeded HybridRetriever), the compactor, or the reader.
Benchmark: tokens fed to the reader
wikimoth.benchmark.harness measures tokens fed to the reader (what you actually pay for) across
arms over the same vault and questions:
arm | feeds the reader | status |
| the whole vault | baseline |
| wikilink-graph retrieval | implemented |
| retrieval + Headroom | implemented |
| an LLM browses and prunes its own context | implemented (Claude tool-use) |
No paid API calls run by default; every arm's reader defaults to the API-free EchoReader.
Honest limits
WikiMoth's value is deterministic, auditable, token-minimal, plain-markdown memory with a real multi-hop capability, not "better retrieval than BM25". Specifically:
The −99% is vs dumping the vault (≈5k vs ~482k tokens on a real 356-note vault), not vs BM25: a tuned BM25-RAG also feeds ~5k. The win is against the realistic status quo (paste everything / naive whole-note RAG), and it's deterministic.
On a typical real vault, retrieval ≈ BM25. Direct-lookup recall@8 ties at 1.00. The multi-hop / connect-the-dots win (0% → up to 100% where flat search scores zero) shows up on curated, link-heavy corpora; on an average vault, hybrid is never worse than BM25, not strictly better on recall.
Determinism is inherent to any static retriever (BM25/dense too); WikiMoth's determinism win is specifically vs LLM-summarised memory (which varies run to run).
vs letting the model prune its own context (the
agenticarm, real run against Claude Sonnet 4.6, 12 multi-hop questions): the agent reaches the same answers, multi-hop included (12/12). The difference is cost. It takes 4 to 6 paid round-trips and about 10x the billed tokens per question, because it re-sends a growing transcript each step, where WikiMoth answers from one deterministic pass with no model call in the retrieval loop and an auditable note-chain. The multiple is corpus-specific, not a law. Reproduce it:python scripts/run_agentic_benchmark.py.
Pluggable + License
MemoryRAG(retriever=…, compactor=…, reader=…); defaults GraphRetriever(source="wikilinks") /
NoOpCompactor / EchoReader. Anything satisfying the small Protocols drops in.
Apache-2.0; see LICENSE. © 2026 Julian Geymonat.
Available Tools
7 toolslist_conflictsA
Deterministically list contradiction CANDIDATES in the WikiMoth vault: notes that assert different values for the same (subject, predicate). No model finds them. Each candidate is for YOU to adjudicate: decide if it is a real contradiction and which note is current. Notes tagged valid-time 'disjoint' are likely a legitimate succession (consider superseding), 'overlapping' is a real conflict. Use before trusting a possibly-stale fact recalled from memory.
| Name | Required | Description | Default |
|---|---|---|---|
| all_keys | No | compare every non-subject key, not just domain facts | |
| include_inline | No | also read Dataview 'key:: value' inline body fields |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the tool is 'deterministic' and 'No model finds them' (indicating it is rule-based). It also clarifies that the result is a list of candidates for the user to adjudicate, not a resolved answer. It mentions the significance of 'valid-time' tags to help interpretation. It does not mention performance, error behavior, or limitations, but for a listing tool this is adequate.
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 three sentences long and front-loaded with the core purpose. Each sentence adds value: the first defines the tool, the second explains the adjudication responsibility, and the third gives usage guidance and tag interpretation. It is compact with no unnecessary filler, earning a strong score though not perfect conciseness.
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 tool's moderate complexity (2 optional boolean parameters) and no output schema, the description covers the essential behavior, expected output (candidates), interpretation guidance, and a use case. It does not specify the exact output format, but with a list tool that is acceptable. The description is complete enough for an agent to decide when and how to use it, even without annotations.
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 schema descriptions cover 100% of the two boolean parameters (all_keys and include_inline). The tool description adds no additional explanation of these parameters, and the baseline is 3 when the schema fully documents them. The description does not enhance understanding of the parameters' impact on results beyond what the schema already states.
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 starts with a clear verb and object: 'list contradiction CANDIDATES' and defines the resource precisely as 'notes that assert different values for the same (subject, predicate)'. This differentiates it from siblings like list_duplicates (which likely finds similar notes) and recall (which retrieves facts).
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 an explicit usage context: 'Use before trusting a possibly-stale fact recalled from memory.' It also explains how to interpret results ('decide if it is a real contradiction and which note is current') and provides guidance on the valid-time tags ('disjoint' vs 'overlapping'). However, it does not explicitly mention when not to use it or name alternative tools, though the use case alone is quite specific.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_duplicatesA
Deterministically find exact and near-duplicate notes (MinHash/Jaccard, no model). WikiMoth capture is append-only and never merges, so content gets restated; this surfaces it. Candidates only: decide which to keep (consider superseding the older one).
| Name | Required | Description | Default |
|---|---|---|---|
| threshold | No | near-duplicate Jaccard threshold in (0,1] (default 0.8) | |
| include_sessions | No | also scan session-* notes (skipped by default) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure, and it does substantial work: it declares determinism, names the algorithm, states that no model is involved, and explains that the output is candidates only rather than an automatic merge. The append-only framing and 'Candidates only' make non-destructive behavior mostly inferable, though an explicit read-only/no-mutation statement would be stronger.
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 three compact sentences, each earning its place: algorithm and scope, domain rationale, and output semantics plus next action. It is front-loaded and contains no filler or repetition of structured schema details.
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 simple tool with two optional, fully documented parameters, the description provides enough to invoke it correctly: what it finds, why it exists, and what to do with the candidates. It lacks an explicit description of the return structure, but since there is no output schema and the tool is a list-style tool, candidate-only semantics plus the forward pointer to supersede are largely sufficient.
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 description coverage is 100%, so threshold and include_sessions are already documented in the schema. The description's mention of Jaccard reinforces the threshold's meaning but adds no new parameter semantics. This matches the baseline of 3 for high schema coverage.
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 opens with a specific action and resource: 'Deterministically find exact and near-duplicate notes'. It further differentiates from the sibling list tools by naming the MinHash/Jaccard method, explicitly saying 'no model', and clarifying that results are candidates rather than automatic actions. This is a focused, non-tautological statement of purpose.
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?
It gives clear context for when the tool is useful: because WikiMoth capture is append-only and never merges, restated content accumulates, and this tool surfaces it. It also advises the user to decide which candidate to keep and to consider superseding the older one, which pairs naturally with the sibling tool supersede. It does not explicitly list alternatives or when not to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_fadingA
Deterministically list the 'fading' review queue: notes going cold (old, rarely linked, rarely recalled), scored by a decay + access + connectivity strength. Read-only, nothing is deleted. Use to suggest what the user might archive, refresh, or supersede.
| Name | Required | Description | Default |
|---|---|---|---|
| tau_days | No | decay time constant in days (default 90) | |
| threshold | No | fading strength threshold (default 0.25) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden for behavioral disclosure. It explicitly states 'Read-only, nothing is deleted,' which is a critical safety trait. It also discloses the deterministic nature and the scoring factors, giving insight into how the list is generated. It does not mention output format or performance, but given read-only hint, it covers the most important behavioral aspect.
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 two sentences with zero waste. It front-loads the core purpose ('list the fading review queue'), then adds the scoring criteria, read-only safety, and a use case. Every sentence earns its place, and the structure flows logically from what to when.
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 no output schema, the description should explain the return value. It says it lists the queue and notes are scored, implying the output is a list of notes with scores, but it doesn't specify fields, ordering, or pagination. However, for a simple read-only list with two optional parameters, this is largely sufficient. The lack of explicit return structure is a minor gap, so a 4 is fitting.
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 schema has 100% coverage, describing tau_days as 'decay time constant in days (default 90)' and threshold as 'fading strength threshold (default 0.25)'. The description adds no additional parameter details; it doesn't even mention the parameters. Since the schema already fully documents them, a baseline score of 3 is appropriate, as the description does not enhance 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 clearly states the tool lists the 'fading' review queue, defines what fading means (notes going cold), and specifies the scoring criteria (decay + access + connectivity). It distinguishes itself from siblings like list_duplicates and list_conflicts by focusing on coldness rather than duplicates or conflicts. Verb and resource are specific, and the purpose is immediately understandable.
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 explicitly says 'Use to suggest what the user might archive, refresh, or supersede,' providing a clear use case. However, it does not mention when NOT to use it or compare directly to any sibling tools, so it lacks explicit exclusions or alternative routing. The context is clear but the guidance is not comprehensive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_lintA
Deterministically report vault-hygiene issues: broken [[links]], orphan notes, duplicate identities, empty stubs, stale/expired notes, and supersession chains/cycles. No model. Read-only. Use to check the memory's structural health or before trusting a possibly-broken link.
| Name | Required | Description | Default |
|---|---|---|---|
| stale_days | No | also flag notes whose mtime is older than N days (0 = off) | |
| include_sessions | No | include session-* notes in orphan/stub/stale checks |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden, and it does well by stating 'No model,' 'Read-only,' and 'Deterministically.' These are meaningful behavioral traits beyond the input schema. It does not describe output format or potential performance characteristics, but for a read-only lint check the disclosed behaviors are sufficient.
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 compact, front-loaded with the core behavior, and each sentence earns its place: what it reports, that it uses no model and is read-only, and when to use it. There is no redundant wording 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?
Given only two optional parameters and no output schema, the description covers purpose, behavior, safety, and usage adequately. It lacks details about the exact return format, but that is a minor gap for a lint/report tool whose scope is clearly enumerated.
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 description coverage is 100%, so the schema already documents both parameters. The description adds 'stale/expired notes' context, which maps to stale_days, but it does not add new meaning about parameter formats or edge cases beyond what the schema provides. 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 states a specific verb ('report'), a clear resource ('vault-hygiene issues'), and enumerates concrete categories (broken links, orphan notes, duplicate identities, etc.). It is not a tautology and is clearly distinct from generic tools, though it does not explicitly differentiate itself from the sibling list_duplicates, which likely overlaps with 'duplicate identities'.
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 gives explicit usage context: 'Use to check the memory's structural health or before trusting a possibly-broken link.' This tells the agent when to invoke it. However, it does not mention when not to use it or how to choose between this and related siblings like list_duplicates or list_conflicts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recallA
Deterministically recall the note-chain from the user's WikiMoth [[wikilink]] memory that answers a question. Walks the authored links (multi-hop), returns the exact notes with NO LLM call to retrieve, far fewer tokens than dumping the whole vault, and the same result every time. Call this before answering anything that might live in the user's notes, memory, or past sessions.
| Name | Required | Description | Default |
|---|---|---|---|
| as_of | No | time-travel: show the vault as it was valid at this ISO date (YYYY-MM-DD) | |
| query | Yes | the question or topic to recall from memory | |
| top_k | No | max note chunks to return (default 8) | |
| show_superseded | No | include superseded note bodies (default false hides them, keeping the edge) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden and does well: it discloses determinism, no LLM call, multi-hop link traversal, token efficiency, and consistent results. It does not mention failure behavior or side effects, but these are less critical for a read-style recall tool.
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 sentences, each earning its place: purpose, behavioral differentiator, and call-time guidance. The key action and resource are front-loaded, with no filler or repetition of schema details.
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 retrieval tool with no output schema, it explains the result concept ('returns the exact notes') and why it is preferable. It could go deeper on output structure or edge cases, but the description is sufficient for an agent to select and invoke the tool 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 description coverage is 100%, so the schema fully documents query, as_of, top_k, and show_superseded. The description adds little parameter-level meaning beyond framing 'query' as a question/topic; 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 uses a specific verb and resource: 'recall the note-chain' from the user's WikiMoth memory, with a clear multi-hop traversal mechanism. It clearly differentiates from sibling list/supersede tools by being a retrieval operation.
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?
Gives explicit when-to-use guidance: 'Call this before answering anything that might live in the user's notes, memory, or past sessions.' It lacks explicit exclusions or alternatives, but the trigger context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusA
Report the connected WikiMoth memory vault: path, note and chunk counts, whole-vault token size, and the token backend. Use to confirm memory is wired up.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full responsibility for behavioral disclosure. It states the output (path, counts, token size, backend) which is the core behavior. It does not explicitly state side effects (though 'report' implies read-only), authentication needs, or error conditions. For a simple status tool this is adequate but not rich, warranting a 3.
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 two concise sentences. The first sentence lists the exact output fields, and the second gives the intended usage. It is front-loaded with the key information and contains no fluff. Every word 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?
Given the tool's simplicity (no parameters, no annotations, no output schema), the description covers all essential information: what it reports and when to use it. It does not specify failure behavior (e.g., if no vault is connected), but that is a minor gap for a status check. It is sufficiently complete for an agent to call it 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?
There are no parameters, so the schema coverage is effectively perfect. The description adds no parameter-specific details, but with zero parameters the baseline is 4. It correctly avoids inventing parameters and simply explains the tool's output rather than inputs.
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 names the specific verb 'Report' and the resource 'connected WikiMoth memory vault', then lists exact metrics (path, note/chunk counts, token size, backend). It clearly distinguishes from sibling tools like list_duplicates, recall, or list_conflicts, which address different concerns. An agent can immediately understand what this tool does.
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 states a clear use case: 'Use to confirm memory is wired up.' It explains when to call it. However, it does not explicitly mention when not to use it or alternative tools, but given its diagnostic nature and lack of overlapping siblings, the guidance is sufficient. It earns a 4 for clear context without exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
supersedeA
Mark an OLD note as replaced by a NEW one, WITHOUT deleting it (invalidate-don't-delete: the file stays, its frontmatter records superseded_by/valid_to/status). Call this AFTER you have adjudicated that NEW genuinely replaces OLD (e.g. from a list_conflicts candidate). OLD/NEW are note stems, slugs, or paths.
| Name | Required | Description | Default |
|---|---|---|---|
| new | Yes | the current note that replaces it | |
| old | Yes | the superseded note (stem/slug/path) | |
| reason | No | optional audit note | |
| reverse | No | also stamp replaces: on NEW |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description takes on the full disclosure burden and does a good job: it states the side effect (frontmatter gains superseded_by/valid_to/status) and reassures that the file itself is not deleted. It does not mention whether existing frontmatter is overwritten or whether write permissions are required, but the core behavioral trait is explicit.
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 sentences, no filler, with the main verb and object first and key constraints in parentheticals. Every sentence earns its place: what it does, when to call it, and how to reference notes.
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 mutation tool with no annotations or output schema, the description provides the preconditions, behavior, and input forms needed to invoke it. It does not discuss return values or failure behavior, but the lack of an output schema makes that less critical; the main gap is the absence of any mention of the reverse parameter in the description, though the schema covers it.
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 the structured schema already documents all four parameters. The description adds a useful identifier-format note ('stems, slugs, or paths') and the adjudication context, but it does not materially deepen parameter meaning 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 opening clause 'Mark an OLD note as replaced by a NEW one, WITHOUT deleting it' states a specific action on a specific resource and immediately separates it from deletion or list-only siblings. The 'invalidate-don't-delete' framing reinforces the intended semantic distinction.
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 gives an explicit precondition: call it only after adjudicating that NEW genuinely replaces OLD, with an example source (list_conflicts). It does not, however, name an alternative tool to use when those criteria are not met, so the guidance stops short of full alternatives/exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.2.3- First observed
list_conflicts - First observed
list_duplicates - First observed
list_fading - First observed
list_lint - First observed
recall - First observed
status - First observed
supersede
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: recall retrieves note-chains; status reports vault metadata; list_duplicates, list_conflicts, list_lint, and list_fading each surface a different kind of maintenance issue; supersede performs the single write action. No two tools could be reasonably confused.
The naming is predominantly snake_case with a consistent list_ prefix for the four inspection tools, and recall/supersede are clear action verbs. The one deviation is 'status', which is a noun rather than a verb_phrase, though it is still intuitive.
Seven tools is well-scoped for the server's purpose of maintaining and recalling from a WikiMoth vault. Each tool addresses a distinct need without redundancy, and the count feels neither thin nor bloated.
The set covers the key lifecycle: detect issues (duplicates, conflicts, lint, fading), adjudicate via recall/status, and resolve via supersede. Minor gaps exist such as no direct 'get_note' or vault-wide listing tool, but recall likely covers most retrieval needs and the core maintenance loop is complete.
Maintenance
Related MCP Connectors
Token-efficient MCP memory for Markdown vaults. Tiered search, GraphRAG, AI memories.
Personal context for every AI: search, read, and write back to your private Markdown library of articles, threads, PDFs, notes, and captured ChatGPT/Claude/Gemini/Grok conversations. OAuth 2.1 paste-and-authorize or revocable tiered Agent keys (read_only / edit / full). Every agent edit is versioned and revertible.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Your portable context layer — load it into any AI.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables semantic search and content retrieval from local Obsidian vaults through the Model Context Protocol. It allows AI assistants to query notes by meaning, filter by tags, and access full note content for enhanced knowledge integration.MIT
- AlicenseAqualityAmaintenanceExposes local markdown documentation, notes, and knowledge bases to AI tools via the Model Context Protocol without embeddings or uploading.41MIT
- FlicenseNot gradedqualityAmaintenanceEnables semantic search and note management for Obsidian vaults via the Model Context Protocol, allowing LLMs to search, read, and index notes, PDFs, and web pages locally.-
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to explore and analyze a markdown vault as a traversable knowledge graph, with tools for searching, traversing, and finding implicit semantic connections between notes.-