wikijs-mcp
# wikijs-mcp
An [MCP](https://modelcontextprotocol.io) server for managing [Wiki.js](https://js.wiki) 2.x
pages: search, read, create, update, move, delete, browse version history, and list assets —
all through the Wiki.js GraphQL API.
## Tools
| Tool | Description |
| ---------------------- | -------------------------------------------------------- |
| `search_pages` | Full-text search across pages. |
| `list_pages` | List pages with ordering, tag, and locale filters. |
| `get_page` | Fetch a page by id or path, including its content. |
| `get_page_tree` | Browse the page hierarchy. |
| `list_tags` | List all tags, or search tags matching a query. |
| `create_page` | Create a new page. |
| `update_page` | Partially update a page by id. |
| `move_page` | Move/rename a page (requires `manage:pages` permission). |
| `delete_page` | Delete a page (destructive). |
| `get_page_history` | Fetch a page's version history trail. |
| `get_page_version` | Fetch the content of a specific historical version. |
| `restore_page_version` | Restore a page to a prior version. |
| `list_assets` | List asset folders and files (read-only). |
## Quick start (stdio)
Add the server to Claude Code with `claude mcp add`:
```bash
claude mcp add wikijs -e WIKIJS_URL=https://wiki.example.com -e WIKIJS_TOKEN=your-api-key-here -- npx @sondt2709/wikijs-mcp
```
For Claude Desktop, Cursor, or any other MCP client that reads a JSON config, add:
```json
{
"mcpServers": {
"wikijs": {
"command": "npx",
"args": ["@sondt2709/wikijs-mcp"],
"env": {
"WIKIJS_URL": "https://wiki.example.com",
"WIKIJS_TOKEN": "your-api-key-here"
}
}
}
}
```
## Getting an API key
1. Log in to your Wiki.js instance as an administrator.
2. Go to **Administration → API Access**.
3. Toggle **Enable API** on.
4. Click **New API Key**, give it a name and expiration, and grant it the permissions
your workflow needs (`read:pages` at minimum; `write:pages`, `manage:pages`, and
`manage:system` for creating/updating/moving/deleting pages).
5. Copy the generated token — it's shown only once — and use it as `WIKIJS_TOKEN`.
## Configuration
| Variable / flag | Default | Description |
| --------------------------- | ------- | ------------------------------------------------------------------- |
| `WIKIJS_URL` / `--url` | — | Base URL of your Wiki.js instance (required). |
| `WIKIJS_TOKEN` / `--token` | — | API key from Administration → API Access (required). |
| `TRANSPORT` / `--transport` | `stdio` | `stdio` or `http`. |
| `PORT` / `--port` | `3000` | Port to listen on when `TRANSPORT=http`. |
| `LOG_LEVEL` / `--log-level` | `info` | pino log level: `fatal`, `error`, `warn`, `info`, `debug`, `trace`. |
CLI flags take precedence over environment variables. See `.env.example` for a template.
## HTTP / Docker mode
Run the server as a long-lived streamable-HTTP service instead of stdio — useful for
sharing one instance across multiple clients, or running behind a reverse proxy.
```bash
cp .env.example .env # set WIKIJS_URL and WIKIJS_TOKEN
docker compose up
```
This builds the image from the included `Dockerfile` and starts the server with
`TRANSPORT=http` on port 3000:
- MCP endpoint: `http://localhost:3000/mcp`
- Health check: `http://localhost:3000/healthz`
Point your MCP client at the `/mcp` endpoint instead of spawning the process directly.
## MCP Inspector
To poke at the server interactively:
```bash
pnpm inspect
```
This builds the project and launches the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
against the stdio transport.
To inspect an HTTP deployment instead, start the server with `docker compose up` (or
`TRANSPORT=http pnpm dev`), then run `npx @modelcontextprotocol/inspector` on its own and
connect the Inspector UI to `http://localhost:3000/mcp` using the "Streamable HTTP"
transport option.
## Development
```bash
pnpm install # install dependencies
pnpm dev # run from source with --watch
pnpm lint # eslint
pnpm typecheck # tsc --noEmit
pnpm format # prettier --write
pnpm build # bundle to dist/
```
End-to-end tests run against a real, disposable Wiki.js instance in Docker:
```bash
pnpm e2e:wiki:up # start local Wiki.js in Docker
pnpm e2e:bootstrap # headless setup: admin account + API key + e2e/.env
pnpm test:e2e # build + run the e2e suite
pnpm e2e:wiki:down # tear down the container and its data
```
See [`e2e/setup.md`](e2e/setup.md) for details, including a manual setup fallback if
the bootstrap script fails.
[Lefthook](https://github.com/evilmartians/lefthook) runs `eslint --fix` and `prettier`
on staged files at `pre-commit`, and `typecheck` + `build` at `pre-push`. It's installed
automatically via the `prepare` script after `pnpm install`.
## Releasing
Pushing a tag matching `v*` (e.g. `v0.2.0`) triggers `.github/workflows/release.yml`,
which lints, typechecks, builds, and publishes the package to npm with provenance.
The `NPM_TOKEN` repository secret must be set (an npm automation token with publish
access to `@sondt2709/wikijs-mcp`) before pushing a release tag, or the workflow will fail at the
publish step.
## License
[MIT](LICENSE)
TDQS
Scored across 13 tools
Each tool targets a distinct resource and action: pages vs tags vs assets, and within pages there are clear separations between listing, searching, fetching, creating, updating, moving, deleting, and history operations. Potential confusions (list_pages vs search_pages, get_page vs get_page_version) are resolved by clear descriptions.
All tool names follow a consistent verb_noun pattern with lowercase snake_case. The verbs (list, search, get, create, update, move, delete, restore) are uniformly used, and nouns clearly indicate the target resource (pages, tags, assets, page_tree, page_history).
13 tools is a well-scoped number for a Wiki.js content management server. The count covers core page lifecycle, search/navigation, history/restore, and auxiliary tag/asset listing without being excessive or too sparse.
The page lifecycle is fully covered (create, read, update, delete, move, list, search, tree, history, restore). The only notable gap is asset management, where only listing is provided (no upload/download/delete), but this is likely outside the tool's primary content-focused purpose.