Knowledge tools have an access problem. Not "hard to get in" - in the sense that different moments in a knowledge workflow need fundamentally different interfaces. A query that runs in a CI pipeline has different output requirements than an exploratory session that might last two hours. An AI agent resolving contradictions overnight has different needs than a human deciding whether to archive a stale page.
Most tools pick one. The CLI that wins for automation is clunky for daily use. The GUI built for interactive browsing can't be called from a script. The chat interface that handles long exploratory sessions can't be composed with other tools.
The question I want to explore: why four interfaces, and why do they all need to point at the same knowledge layer?
The examples in this post use Synthadoc, an open-source AI knowledge base tool, as the reference implementation. The architectural pattern applies more broadly.
The Architecture

All four interfaces share the same storage, the same lifecycle states, and the same audit trail. The core doesn't care which surface a request comes from - a lifecycle transition triggered by an AI agent at 2 AM is recorded the same way as one triggered by a human from the CLI.
The key design principle: the knowledge layer has opinions. It enforces a lifecycle transition graph. It writes audit records. It tracks provenance. These constraints apply regardless of which interface makes the call, which is what makes it safe to connect a reasoning model to the same layer a human is using.
Four Interfaces, Four Different Moments
CLI: When a Query Is a Step in Something Larger
The CLI is for automation. Not because the other surfaces are inconvenient from the terminal, but because the CLI is the only one that emits clean structured output you can pipe somewhere.
# Streaming to terminal — tokens appear as the LLM generates them
synthadoc query "What changed in the computing landscape after the transistor?"
# Script mode — waits for the full response, stdout is a clean JSON blob
synthadoc query "Summarize the von Neumann architecture" --no-stream | jq .answer
# Post-ingest verification in CI — check a page was compiled and is active
synthadoc lifecycle log alan-turing | grep "draft → active"
The --no-stream flag exists specifically for automation. Streaming tokens are great when a human is watching; they're noise in a pipeline. A scheduled ingest + lint + check script doesn't want token-by-token output, it wants a complete response when done.
The CLI is also where operations live that aren't questions: running lint checks, checking status, promoting candidates, scheduling nightly ingests. None of that belongs in a chat window.
IDE/App Plugin: When You're Already in the Knowledge Base
The Obsidian plugin exists because a lot of the work that happens around a knowledge base happens inside the writing tool. You're authoring a note, checking a claim, finding related pages, reviewing which pages went stale after last night's ingest. Opening a terminal for that is friction you don't need.
The query modal renders [[wikilinks]] in answers as clickable links. That's not cosmetic, it means an answer referencing three related pages gives you direct navigation to all three, a fundamentally different experience from reading the same text in a terminal.
The lifecycle management view is where this really earns its place. It's a sortable, filterable table of every page in the knowledge base with its current state, last transition timestamp, and the valid action buttons for that state. This is the part that requires a human decision: does this contradicted page need revision, or should it be archived? That decision should happen in context, inside the tool where you read and write content.
A design decision worth highlighting: the knowledge base files are valid Obsidian vault files. Your existing Obsidian workflows apply. Dataview can query the orphan:, status:, and type: frontmatter fields. The graph view shows the full wikilink topology. Staying ecosystem-compatible means the tool inherits every Obsidian plugin without having to build equivalents. The plugin adds compilation and lifecycle capabilities to a tool knowledge workers already live in, it doesn't replace the host environment.
Web Chat UI: When You Want a Session, Not a Command
The web chat UI exists for exploratory sessions that are too long for a modal and too conversational for the CLI. Nothing leaves the machine, no cloud service beyond the LLM provider already configured.
What this surface adds that the others don't: operational commands in natural language. "Run lint", "show me the stale pages", "schedule ingest every night at midnight" - the Action Agent parses these and executes them live, with results shown inline. When you're deep in a working session and need to check knowledge base health, typing it in the same window is less disruptive than switching terminals.
It's also the most effective demo surface. A few typed questions in a local browser tab gets the point across faster than any terminal walkthrough.
MCP: When a Reasoning Model Should Be Doing the Work
This is the one that changes the conceptual model.
The CLI, plugin, and web chat UI all answer queries. The system reads relevant pages, synthesizes an answer, and delivers it. The quality of reasoning is bounded by the configured model, the token budget, and the deterministic hint engine that generates follow-up suggestions.
MCP reverses the direction. Instead of the knowledge system calling an LLM to answer a question, a reasoning model, Claude Desktop, Claude Code, or any MCP-compatible agent, calls the knowledge system's tools to access and edit the base. The model does the reasoning. The knowledge layer does storage, retrieval, and lifecycle tracking.
QUERY SURFACE MODEL
User → Knowledge System → [BM25 retrieval + LLM synthesis] → Answer
MCP MODEL
User → Reasoning Model → [Model decides what to search, read, write, transition] → Knowledge Layer → Result
This isn't a subtle difference. In the MCP model, Claude can chain tool calls based on what it finds. It can read a contradicted page, search for related pages, synthesize a resolution, write the updated content, and transition the lifecycle state - all in one prompt, with each step informed by the previous. A deterministic hint engine can't generate that chain dynamically. A reasoning model can, because it reasons.
You Don't Need All Four — But Each One Earns Its Place
The four interfaces are not a required bundle. Most users settle into a combination:
- CLI + Plugin + Web UI: the natural setup for knowledge workers who aren't running AI agent workflows. Ingest and maintain from the terminal, browse and query inside the writing tool, use the web UI for exploratory sessions or demos. MCP never enters the picture, and that's completely fine.
- CLI + Plugin + MCP: when automated editorial workflows are the goal. An AI agent ingests and resolves contradictions overnight; you review results in the writing tool the next morning. The web UI is useful but not central.
- All four: valid in team settings where different members use different surfaces. Adding MCP doesn't change how the CLI behaves; installing the plugin doesn't require the web UI running.
The decision isn't "which one is right", it's "which combination fits the workflow you actually have."
The Brain and Memory Split
MCP makes explicit a division of responsibility that was always there but often muddled.
The reasoning model is the brain. Synthesis, editorial judgment, multi-step reasoning, dynamic tool selection. It reads the lint report, decides which contradictions are resolvable, writes the resolution, and selects the appropriate lifecycle transition.
The knowledge layer is the memory. BM25 retrieval/vector search, lifecycle tracking, provenance, immutable audit trail. It doesn't decide what to do with a contradicted page, it stores the fact that it's contradicted, records every change, and enforces the transition graph when the model tries to move it.
When Claude calls write_page then lifecycle_transition to mark a page active, the same audit record is written as if a human had done it from the CLI. The triggered_by field records mcp. The reason string is Claude's stated rationale. Run the lifecycle log afterwards and the full chain is there.
This is also why the deterministic hint engine doesn't disappear with MCP. It serves humans querying the knowledge base - no LLM cost, instant suggestions. Claude generates its own next steps dynamically when editing the base. Two different users, two different workflows.
Two Ways to Consume the Knowledge Layer
There are two paths for external agents to consume what the system has compiled. They're not interchangeable.

Why You Can't Just Point an Agent at the Raw Files
Knowledge tools like Obsidian use [[wikilinks]] - non-standard, host-app-only. Standard CommonMark requires [display](slug.md). An external agent reading raw vault files encounters broken links.
A proper export rewrites every link, generates an index.md grouped by entity type, and writes a log.md from the lifecycle audit trail. Export once, consume anywhere, no server needed.
The live MCP path has the opposite properties: always freshest data, supports two-way writes, full lifecycle enforcement. Trade-off: requires a running server and an agent that speaks MCP.
Two Directions This Architecture Grows Into
Direction 1: Persistent Memory for AI Workflows
Reasoning models are good at synthesis and multi-step planning, but they start each session with no memory of the last one. Every task re-derives context from scratch. The session window is the boundary.
A lifecycle-tracked knowledge layer doesn't have that boundary. A page compiled last month is still there. Its lifecycle state tells you whether it was reviewed recently or has gone stale. Connect a reasoning model to the knowledge layer via MCP and it has a persistent domain knowledge base to search, read, write, and maintain - across sessions, across agents.
The direction this grows toward: the knowledge layer as shared persistent memory in multi-agent pipelines. One agent ingests sources overnight. Another resolves contradictions. A third answers queries. All three read from the same lifecycle-tracked, audit-trailed base. None re-derive domain knowledge from scratch.
One constraint worth noting: the knowledge layer enforces the lifecycle transition graph regardless of which agent calls it. A model can't move a page from stale to contradicted any more than a CLI user can. The memory layer has opinions about consistency, even when the brain doesn't.
Direction 2: Portable Knowledge Bundles
The second direction decouples the knowledge from the runtime. An export pipeline means the knowledge layer can be the compilation and maintenance tool for a base that lives on independently. Build it with the pipeline - ingest, LLM compilation, adversarial lint, lifecycle tracking. Export it once it's clean. The bundle goes anywhere: a third-party agent, an offline analysis tool, a compliance archive.
A typed entity model is what makes the bundle useful to a consuming agent. Without typed entities, an agent has to infer whether a page is about a person, a technology, or an event. With type: person in frontmatter, it knows immediately.
synthadoc export --format okf --status active
# → exports/<wiki-name>-okf-<date>/
What the Four-Interface Model Actually Tells You
The through-line across all four interfaces is that compiling knowledge and storing knowledge are different operations, and the compilation pipeline should be the same regardless of which surface queries the result.
What MCP specifically adds is a bidirectional connection to models that are better at synthesis than a deterministic query pipeline. A lint agent is fast, cheap, and good at detecting contradictions. A reasoning model is slower, more expensive, and genuinely better at deciding what a balanced resolution looks like. Those aren't competing features; they're complementary stages in the same pipeline.
The audit trail is what makes this work at scale. Whether a lifecycle transition comes from a nightly lint run, a CLI command, or a reasoning model at 2 AM, the same record is written and the same graph enforcement applies. The memory layer doesn't care which brain issued the instruction.
Reference Implementation
If you want to see this pattern in a working system, Synthadoc is the open-source implementation described in this post. The quick-start guide covers Obsidian plugin setup and configuration, MCP setup, contradiction resolution walkthrough, and export documentation including Google's Open Knowledge Format (OKF) export bundle.
Running locally against the history-of-computing demo wiki takes about ten minutes:
git clone https://github.com/axoviq-ai/synthadoc.git
pip install -e ".[dev]"
synthadoc install history-of-computing --target ~/wikis --demo
synthadoc plugin install history-of-computing
synthadoc use history-of-computing # set as default — no -w needed from here
synthadoc serve # starts HTTP + MCP on port 7070
To connect Claude Code as a reasoning brain over the wiki:
claude mcp add --transport sse synthadoc-history-of-computing http://127.0.0.1:7070/mcp/sse
Github repo: https://github.com/axoviq-ai/synthadoc.