<p align="center">
<img src="src/www/images/_raydeStar.png" alt="WikiMCP" width="120" />
</p>
<h1 align="center">WikiMCP</h1>
<p align="center">
MCP server for a Wiki.js project. Provides full-text search, page retrieval, and optional page creation via the Model Context Protocol.
</p>
## What this repo gives you
- **A Wiki.js stack** (Wiki.js + Postgres) you can run locally with Docker.
- **An MCP server** (Node/TypeScript) that exposes Wiki tools over **stdio** (spawned by a client like LM Studio / Cursor / Claude Desktop).
- **Receipts-first tooling**: `wiki.quote` returns exact line ranges so answers can cite sources.
---
## Architecture in one picture
```text
┌──────────────┐ ┌───────────────────────┐
│ MCP Client │ │ Wiki.js (UI) │
│ (LM Studio / │ │ + Postgres │
│ Cursor / …) │ └──────────┬────────────┘
└──────┬───────┘ │
│ spawns (stdio) │
▼ │ reads/imports
┌───────────────────────┐ │ markdown
│ WikiMCP (this repo) │◄─────────┘
│ - tools: search/get/ │
│ quote/list/(create) │
└───────────────────────┘
```
**Important:** Docker is for **Wiki.js + Postgres**. The MCP server is typically spawned directly by your MCP client (no Docker required for the MCP server unless you want it).
---
## Quick Start (sample data)
```powershell
git clone https://github.com/raydeStar/WikiMCP WikiMCP
cd WikiMCP
.\bootstrap-local.ps1 -OpenUi
```
- Wiki.js opens at: `http://localhost:3030`
- The stack includes sample content in `./wiki-content`
---
## Setup paths (choose your adventure)
### 1) Local with sample data (default)
```powershell
.\bootstrap-local.ps1 -OpenUi
```
Uses `./wiki-content` (characters, locations, chapters, etc.).
### 2) Local with empty wiki
```powershell
.\bootstrap-local.ps1 -ContentMode Empty -OpenUi
```
Creates `./wiki-content-empty` with just the `en/` locale folder (sample data stays untouched).
### 3) Local with custom content path
```powershell
.\bootstrap-local.ps1 -ContentMode Path -ContentPath "D:\my-wiki" -OpenUi
```
Points to any folder on your machine.
### 4) Reset everything (wipe DB, keep content)
```powershell
.\bootstrap-local.ps1 -Reset -OpenUi
```
Removes Docker volumes and rebuilds from scratch. Your content folder survives.
---
## Wiki.js first-run setup
After containers start:
1. Open `http://localhost:3030`
2. Complete the Wiki.js setup wizard (create admin account)
3. Go to **Administration → Storage → Local File System** (or Git)
4. Set the path to: `file:///wiki-storage`
5. Click **Apply** and **Import Everything**
Your markdown files will appear in the wiki.
---
## Connect an LLM / MCP client (the fun part)
WikiMCP communicates via **stdio** (stdin/stdout). Your MCP client spawns the server directly.
### 1) Build the MCP server
```powershell
npm install
npm run build
```
This produces `dist/index.js`.
### 2) Configure your MCP client
#### Cursor / Claude Desktop (example)
Add to your MCP config (example file: `mcp-config.example.json`):
```json
{
"mcpServers": {
"novel-wiki": {
"command": "node",
"args": ["dist/index.js"],
"cwd": "C:/Users/YourName/WikiMCP",
"env": {
"WIKI_REPO_PATH": "C:/Users/YourName/WikiMCP/wiki-content",
"WIKI_WRITE_ENABLED": "false",
"MCP_AUTH_USERNAME": "",
"MCP_AUTH_PASSWORD": ""
}
}
}
}
```
Adjust paths for your system.
#### LM Studio (concept)
LM Studio can act as an MCP host as well. Add a server entry that spawns:
- `node dist/index.js` …and pass `WIKI_REPO_PATH` to point at your content directory.
---
## MCP vs REST/Swagger (1-minute version)
If you’re used to normal APIs, MCP can feel weird at first. Here’s the simple mapping:
- **REST/Swagger:** You design lots of URLs like `GET /pages/{id}` and document them in OpenAPI.
- **MCP:** You expose a **tool list** (functions) like `wiki.search`, `wiki.get_page`, `wiki.quote` with JSON schemas.
In other words:
- REST is **resource-oriented** (endpoints)
- MCP is **capability-oriented** (tools)
A typical REST call:
- `GET /api/wiki/pages/Tim`
A typical MCP call (conceptually):
- `call tool wiki.get_page({ path: "/characters/white-bunny" })`
The MCP client/host (LM Studio, Cursor, etc.) is the thing that:
1. discovers the tool list
2. decides when to call a tool
3. feeds tool results back into the model
---
## MCP Authentication (optional) (optional)
If `MCP_AUTH_USERNAME` and `MCP_AUTH_PASSWORD` are both set, every tool call must include:
```json
{
"auth": {
"username": "your-user",
"password": "your-pass"
},
"query": "The Knights who say Ni"
}
```
Bootstrap helpers:
```powershell
.\bootstrap-local.ps1 -AuthFromDb
```
or:
```powershell
.\bootstrap-local.ps1 -McpAuthUsername "admin" -McpAuthPassword "secret"
```
---
## Write operations
`wiki.create_page` is **disabled by default**.
Enable it by either:
1. `.env`:
- set `WIKI_WRITE_ENABLED=true`
- ensure your wiki content mount is not read-only
or
2. bootstrap flag:
```powershell
.\bootstrap-local.ps1 -WriteEnabled
```
---
## Available MCP tools
| Tool | Description |
| ------------------------ | ---------------------------------------------------------------- |
| `wiki.search` | Full-text search with optional filters (type, tags, path prefix) |
| `wiki.get_page` | Retrieve full page content by path |
| `wiki.quote` | Extract specific lines from a page (citations/receipts) |
| `wiki.list` | List pages, optionally filtered by type or tag |
| `wiki.reindex` | Rebuild the search index |
| `wiki.get_context_bundle`| Get everything about a topic: main page, related pages, summaries, citations |
| `wiki.create_page` | Create a new page (requires `WIKI_WRITE_ENABLED=true`) |
### wiki.get_context_bundle (the power tool)
This is the bridge between librarian and editor. Instead of orchestrating multiple calls, ask:
```json
{ "topic": "Kazalt", "maxPages": 5 }
```
Returns:
- **mainPage**: Full content of the best-match page
- **relatedPages**: Summaries of linked and related pages
- **citations**: Version info for every page (receipts)
- **totalPagesFound**: How many matches exist
The model can now say *"give me everything about X"* and get a ready-to-use context bundle.
---
## Environment variables
| Variable | Description | Default |
| -------------------- | ------------------------------------ | ------------------------- |
| `WIKI_DB_NAME` | Postgres database name | `wikijs` |
| `WIKI_DB_USER` | Postgres username | `wikijs` |
| `WIKI_DB_PASSWORD` | Postgres password | *(required)* |
| `WIKI_CONTENT_DIR` | Content folder path (Docker/Wiki.js) | `./wiki-content` |
| `WIKI_WRITE_ENABLED` | Enable `wiki.create_page` | `false` |
| `MCP_AUTH_USERNAME` | MCP auth username | *(empty)* |
| `MCP_AUTH_PASSWORD` | MCP auth password | *(empty)* |
| `WIKI_REPO_PATH` | Content path used by MCP server | `/wiki` |
| `DB_PATH` | SQLite index path | `/app/data/wiki-index.db` |
---
## Project structure
```text
WikiMCP/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── indexer.ts # SQLite FTS indexer
│ └── config.ts # Environment config
├── wiki-content/ # Sample markdown content
├── docker-compose.yml # Local dev stack (Wiki.js + Postgres)
├── docker-compose.prod.yml # Production overrides
├── bootstrap-local.ps1 # PowerShell setup script
├── Dockerfile # Optional container for MCP server
└── .env.example # Environment template
```
---
## Troubleshooting
### “password authentication failed”
Old Postgres volume credentials. Reset:
```powershell
.\bootstrap-local.ps1 -Reset
```
### “detected dubious ownership in repository”
Git safety check. The compose file configures `safe.directory`. Restart:
```powershell
docker compose restart wiki-js
```
### MCP server not connecting
- Ensure `npm run build` succeeded
- Ensure absolute paths in the MCP client config
- Ensure `WIKI_REPO_PATH` points to real content
---
## How this differs from a normal REST API (quick intuition)
WikiMCP is **not** a traditional HTTP API meant for humans or frontends.
- A REST API exposes *endpoints* (URLs) and HTTP verbs.
- An MCP server exposes *tools* (named capabilities with JSON schemas).
In practice:
- Your MCP client (LM Studio, Cursor, Claude Desktop) **spawns this server**.
- The server advertises its tools (e.g. `wiki.search`, `wiki.quote`).
- The LLM decides *which tool to call* and with what arguments.
- WikiMCP enforces validation, permissions, and returns structured results.
Think of it as **"controllers for an AI client"** rather than endpoints for a web app.
If you understand that one sentence, you understand MCP well enough to build useful things.
---
## When *not* to use WikiMCP
WikiMCP is intentionally simple. You probably *should not* use it if:
- You only want a normal REST API over your wiki
- You don’t need citations or exact quotes
- You don’t plan to use an LLM with tool-calling
WikiMCP shines when:
- You want an LLM to *prove where it got information*
- You’re experimenting with agents, RAG, or MCP
- You want a clean learning project that scales into something real
---
## License
This project is licensed under the **GNU Affero General Public License v3.0 (AGPL-3.0)**.
WikiMCP intentionally mirrors the license of **Wiki.js**, which is also AGPL-3.0. This ensures:
- Clear legal alignment with the upstream project
- Transparency for anyone running modified versions as a service
- A shared expectation that improvements remain open
If you are unfamiliar with AGPL, the practical takeaway is simple:
> If you modify this project and make it available to users over a network, you must provide the source code of your modified version.
For personal use, learning, tinkering, and local deployments, AGPL imposes no additional burden.
See the `LICENSE` file for full terms.
---