# Wiki.js + Novel Wiki MCP Server Design (LM Studio + Agent Gateway)
## 0) Purpose
Build a **fully functional (not polished)** system where an LLM (via LM Studio) can reliably:
* Read your wiki pages (chapters, characters, locations, magic rules)
* Search and quote with receipts
* Support later “agent tasks” (continuity reports, rewrite suggestions, research)
Design priorities:
1. **Simple first** (works end-to-end)
2. **Receipts** (stable citations)
3. **Seams for future split** (continuity/research/agents)
---
## 1) Big-picture architecture
```text
┌──────────────────────────────┐
│ Client(s) │
│ - Web UI / CLI │
│ - Cron / Scheduler │
└───────────────┬──────────────┘
│ HTTPS JSON
▼
┌──────────────────────────────────────────────┐
│ Agent Gateway / Runtime │
│ - session + prompt builder │
│ - tool registry (MCP tools) │
│ - tool-call executor + guardrails │
│ - output formatting (citations) │
└───────────────┬──────────────────────────────┘
│ OpenAI-compatible API
▼
┌──────────────────────────────┐
│ LM Studio (LLM host) │
│ /v1/chat/completions │
└───────────────┬──────────────┘
│ tool calls
▼
┌───────────────────────────────────────────────────────────┐
│ MCP Servers (can be 1 process now, split later) │
│ - novel.wiki (Wiki.js-backed) │
│ - (later) novel.continuity │
│ - (later) research │
└───────────────┬───────────────────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ Wiki.js (authoring UI) │
│ - pages, tags, links │
│ - auth + roles │
└───────────────┬──────────────┘
│ storage
▼
┌──────────────────────────────┐
│ Wiki Storage + Indexes │
│ - Postgres (Wiki.js) │
│ - Git repo or filesystem │
│ - (optional) Qdrant/pgvector │
└──────────────────────────────┘
```
---
## 2) Key design decision: how MCP reads Wiki.js content
### **Wiki.js → Git storage → MCP reads repo**
* Configure Wiki.js storage to **sync pages to a Git repository**.
* MCP server reads Markdown from that repo (fast, simple, versioned).
Why this is the cleanest:
* Citations can include **commit SHA** (gold-standard receipts).
* Incremental indexing is easy (diff changed files).
* Zero “wiki API drift” risk.
---
## 3) Data model (wiki pages as first-class “documents”)
Each wiki page becomes a document with metadata:
* `doc_id` (stable id, or derived from path)
* `type` (chapter | character | location | system | artifact)
* `title`
* `path` (wiki path / slug)
* `tags` (Kazalt, Frastown, Aetherwood)
* `links` (outgoing wiki links)
* `updated_at`
* `version` (commit SHA if Git storage)
* `body_md` (Markdown)
Folder/path conventions (suggested):
```text
/chapters/01-the-arrival
/chapters/02-the-levy
/characters/kazalt
/characters/ennix
/locations/frastown
/systems/magic-aetherwood
/artifacts/leviathan-chain
```
---
## 4) `novel.wiki` MCP Server (the librarian)
### 4.1 Responsibilities
* Validate inputs (schemas + domain constraints)
* Enforce access (caller identity + allowlists)
* Fetch ground truth pages (Git or Wiki.js API)
* Provide **search + quotes + citations**
* Normalize outputs so the LLM can’t misinterpret
### 4.2 Internal modules
```text
novel.wiki MCP
├─ Auth middleware (HMAC/JWT from Agent Gateway)
├─ Page Store
│ ├─ GitPageStore (reads repo)
│ └─ WikiApiPageStore (calls Wiki.js)
├─ Parser
│ ├─ front-matter extraction
│ └─ link/tag extraction
├─ Index
│ ├─ Lexical search (SQLite FTS or OpenSearch)
│ ├─ Vector search (optional: Qdrant/pgvector)
│ └─ Rerank (optional later)
├─ Citation Builder
│ ├─ {path, heading?, line_start, line_end, version}
│ └─ stable anchors for quotes
└─ Observability
├─ request logs + tool calls
└─ cache hit rates
```
---
## 5) Tool surface (MVP tools)
### 5.1 Tool: `wiki.search`
**Purpose:** Find relevant pages/snippets.
Input:
* `query: string`
* `filters?: { type?: string, tags?: string[], path_prefix?: string }`
* `k?: number` (default 10)
Output:
* `matches: [{ score, title, path, snippet, citation }]`
Citation format:
* `citation: { path, version, line_start?, line_end?, heading? }`
---
### 5.2 Tool: `wiki.get_page`
**Purpose:** Fetch full page for deeper reasoning.
Input:
* `path: string`
Output:
* `{ title, path, type, tags, links, version, body_md }`
---
### 5.3 Tool: `wiki.quote`
**Purpose:** Return exact excerpt (for receipts).
Input:
* `path: string`
* `line_start: number`
* `line_end: number`
Output:
* `{ text, citation }`
Rule: This tool is the only way to get “exact words” into the answer.
---
### 5.4 Tool: `wiki.list`
**Purpose:** List pages for navigation.
Input:
* `type?: string`
* `tag?: string`
Output:
* `pages: [{ title, path, type, updated_at, version }]`
---
## 6) Indexing strategy (keep it boring at first)
### MVP indexing (do this first)
* **Lexical search only** (SQLite FTS is enough for 1-book scale).
* Build an index from Markdown pages on startup, and refresh on a schedule.
### Next step (when lexical feels limiting)
Add embeddings:
* Create chunked passages per page (headings/paragraphs)
* Store embeddings in Qdrant or pgvector
* Implement hybrid retrieval: lexical → vector → merge
### Refresh triggers
* If using Git storage: watch repo changes (or run `git pull` on interval) and reindex only changed files.
* If using Wiki API: poll `updated_at` and reindex deltas.
---
## 7) Dockerized deployment (simple compose)
### 7.1 MVP docker-compose (concept)
```text
services:
agent-gateway:
lm-studio:
wiki-js:
wiki-db (postgres for wiki.js):
novel-wiki-mcp:
(optional later) qdrant:
```
### 7.2 Networking notes
* Agent Gateway calls LM Studio at `http://lm-studio:1234/v1/chat/completions` (or host.docker.internal)
* Agent Gateway calls MCP at `http://novel-wiki-mcp:8080/...` (or stdio transport)
* Wiki.js UI at `http://localhost:3000`
### 7.3 Storage volumes
* `wiki-db` volume
* `wiki-git-repo` volume (if Git storage)
* `mcp-index` volume (SQLite FTS + caches)
---
## 8) End-to-end request flows
### 8.1 Canon lookup (“Where is Kazalt described?”)
1. User asks in chat
2. Agent Gateway sends prompt + tools to LM Studio
3. Model calls `wiki.search({query: "Kazalt description"})`
4. MCP returns matches + citations
5. Model may call `wiki.get_page` or `wiki.quote` for exact excerpt
6. Final answer includes receipts
### 8.2 Editing assistance (“Improve Chapter 3 dialogue”)
1. Model calls `wiki.get_page(/chapters/03-...)`
2. Gateway optionally fetches relevant canon pages (characters referenced)
3. Model proposes edits (output as structured “suggestion list”)
4. (Later) Agent task can apply changes back to Wiki.js via API or Git commit
---
## 9) Guardrails (where correctness lives)
### 9.1 MCP server must enforce
* Schema validation
* Path allowlists (don’t let the model read secrets outside the wiki repo)
* Output normalization
* Quote bounds (max lines per quote)
### 9.2 Agent Gateway should enforce
* Which tools are available per route (chat vs cron)
* Timeouts and retries
* Audit logs
---
## 10) Extension plan (agents later, cleanly)
### Phase 1: Working librarian (1–2 evenings)
* Wiki.js + Git storage
* `novel.wiki` MCP with `search/get_page/quote/list`
* SQLite FTS index
### Phase 2: Continuity accountant
Add `novel.continuity` MCP:
* Precompute character appearances per chapter
* Tool: `continuity.last_appearances(character, n)`
### Phase 3: Fact checker
Add `research` MCP:
* Web lookup with citations
* Domain allowlist + caching
### Phase 4: Agent tasks
Add an “agent runner” (in Gateway or separate service) that can:
* Nightly contradiction reports
* Weekly editorial brief
* “Suggest edits, but do not apply”
* Later: “Apply suggestions as a Git PR”
---
## 11) What “fully functional” means for MVP
A system is MVP-done when you can:
* Edit pages in Wiki.js
* Ask the assistant questions in chat
* Watch it call `wiki.search` + `wiki.quote`
* See answers with citations that match your source
* Run a cron job that posts a summary (e.g., “Kazalt appearances last 5 scenes”)
---
Sir Thaddeus’ Note: Start with Git-backed wiki pages + lexical search + quoting. Embeddings and fancy agents come later. Receipts first; wizardry second.