The Wiki.js MCP Server enables Claude to interact directly with your Wiki.js instance via the Model Context Protocol (MCP). Create, update, search, and manage wiki pages directly from Claude Code - without manual copy-paste or browser switching.
This MCP server enables Claude to interact directly with Wiki.js - without manual copy-paste or browser switching. Documentation is automatically generated while you develop.
1. Automatic Documentation After Plugin Development
You develop a plugin in Claude Code and say: "Create a comprehensive wiki page for this." Claude analyzes the code, architecture, and API and automatically creates a structured wiki page.
2. Knowledge Management During Development
Search Wiki.js for existing documentation and apply found conventions to your current code.
3. Content Reorganization
Systematically move pages between paths, e.g., all pages under /legacy/ to /archive/.
4. Multilingual Documentation
Create wiki pages simultaneously in DE and EN with consistent structure.
5. Batch Updates
Efficiently update tags, descriptions, or publication status of multiple pages.
| Requirement | Version | Notes |
|---|---|---|
| Node.js | 18+ | Runtime environment |
| Wiki.js | 2.x or 3.x | With GraphQL API enabled |
| Wiki.js API Token | - | Permissions: read:pages, write:pages, manage:pages |
| Claude Desktop or CLI | Current | As MCP client |
| npm | 8+ | Package manager |
npm install -g @markus-michalski/wikijs-mcp-server
Then register in Claude Code:
claude mcp add -s user wikijs -- wikijs-mcp-server
# Create MCP server directory
mkdir -p ~/.claude/mcp-servers/wikijs
# Clone repository
git clone https://github.com/markus-michalski/wikijs-mcp-server.git ~/.claude/mcp-servers/wikijs
# Install dependencies and build
cd ~/.claude/mcp-servers/wikijs
npm install
npm run build
Then register in Claude Code:
claude mcp add -s user wikijs node ~/.claude/mcp-servers/wikijs/dist/index.js
| Variable | Required | Default | Description |
|---|---|---|---|
WIKIJS_API_URL |
Yes | - | GraphQL endpoint of the Wiki.js instance (e.g., https://wiki.example.com/graphql) |
WIKIJS_API_TOKEN |
Yes | - | API token with page management permissions |
The server automatically loads the .env file from ~/.claude/mcp-servers/wikijs/.env at startup. Falls back to .env in the current directory.
# Create .env file
cp .env.example ~/.claude/mcp-servers/wikijs/.env
Edit ~/.claude/mcp-servers/wikijs/.env:
WIKIJS_API_URL=https://your-wiki-instance.com/graphql
WIKIJS_API_TOKEN=your-api-token-here
You do NOT need to set environment variables in the Claude MCP configuration. The server loads them automatically from the
.envfile.
Claude Code MCP Serverread:pages - Read pageswrite:pages - Create and update pagesmanage:pages - Delete and move pages.env fileWithout
manage:pages,delete_pageandmove_pagewill not work. If you only need read/write access,read:pagesandwrite:pagesare sufficient.
{
"mcpServers": {
"wikijs": {
"command": "node",
"args": ["/home/YOUR_USERNAME/.claude/mcp-servers/wikijs/dist/index.js"],
"env": {}
}
}
}
# Register globally (recommended)
claude mcp add -s user wikijs node ~/.claude/mcp-servers/wikijs/dist/index.js
# Verify registration
claude mcp list
Without
-s user, the server is only registered for the current directory and won't be available in other projects.
After restarting Claude Code:
/mcp
You should see wikijs with status "connected".
| Tool | Description | Parameters |
|---|---|---|
wikijs_create_page |
Create a new wiki page | path, title, content, description, locale, editor, isPublished, isPrivate, tags |
wikijs_update_page |
Update an existing page | id/path, locale, content, title, description, isPublished, tags |
wikijs_get_page |
Retrieve a page by ID or path | id/path, locale |
wikijs_list_pages |
List pages with pagination | locale, limit, offset |
wikijs_search_pages |
Full-text search | query, locale |
wikijs_delete_page |
Permanently delete a page | id/path, locale |
wikijs_move_page |
Move a page to a new path | id/path, locale, destinationPath, destinationLocale |
Creates a new page in Wiki.js.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | - | Page path without leading slash (e.g., osticket/plugin-name) |
title |
string | Yes | - | Page title (max 200 chars) |
content |
string | Yes | - | Page content (Markdown or HTML) |
description |
string | Yes | - | Short page description (max 500 chars) |
locale |
string | No | en |
Language (2-5 chars) |
editor |
string | No | markdown |
Editor type: markdown, code, ckeditor |
isPublished |
boolean | No | true |
Publish immediately |
isPrivate |
boolean | No | false |
Private page with restricted access |
tags |
string[] | No | [] |
Tags for categorization |
Example:
{
"path": "osticket/ticket-merge-plugin",
"title": "Ticket Merge Plugin",
"content": "# Technical Documentation\n\n...",
"description": "Technical documentation for the Ticket Merge Plugin",
"locale": "en",
"isPublished": true,
"tags": ["osticket", "plugin"]
}
Updates an existing page. Identification by ID or path+locale.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
id |
number | No* | - | Page ID |
path |
string | No* | - | Page path |
locale |
string | No | en |
Language (required when using path) |
content |
string | No | - | New content |
title |
string | No | - | New title (max 200 chars) |
description |
string | No | - | New description (max 500 chars) |
isPublished |
boolean | No | - | Publication status |
tags |
string[] | No | - | New tags array |
*Either id or path must be provided.
Auto-Content Preservation: If
contentortagsare not provided, existing values are automatically fetched from the server and preserved. This allows metadata-only updates without content loss.
Examples:
// Metadata-only update (content is preserved)
{ "id": 8, "isPublished": true }
// Update content by path
{
"path": "osticket/plugin-name",
"locale": "en",
"content": "# New Content\n\n...",
"isPublished": true
}
Retrieves a page by ID or path.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
id |
number | No* | - | Page ID |
path |
string | No* | - | Page path |
locale |
string | No | en |
Language (required when using path) |
*Either id or path must be provided.
The
get_pagetool does not return tags. This is a limitation of the Wiki.js GraphQL API. Uselist_pagesinstead and filter by ID or path.
Content over 100,000 characters is automatically truncated with the notice
[Content truncated. Original length: XXX chars].
Lists all pages with pagination and optional filtering. This tool also returns tags.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
locale |
string | No | - | Filter by language |
limit |
number | No | 50 |
Maximum results (1-200) |
offset |
number | No | 0 |
Number of entries to skip |
Pagination Response:
{
"pagination": {
"limit": 50,
"offset": 0,
"total_count": 120,
"has_more": true,
"next_offset": 50
}
}
Full-text search across all wiki content.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | Yes | - | Search query (2-200 chars) |
locale |
string | No | - | Filter by language |
Permanently and irreversibly deletes a page. Identification by ID or path+locale.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
id |
number | No* | - | Page ID |
path |
string | No* | - | Page path |
locale |
string | No | en |
Language (required when using path) |
*Either id or path must be provided.
This action is IRREVERSIBLE! The page and all its history will be permanently deleted.
Moves a page to a new path. Identification by ID or path+locale.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
id |
number | No* | - | Page ID |
path |
string | No* | - | Current page path |
locale |
string | No | en |
Current language |
destinationPath |
string | Yes | - | New path (1-500 chars) |
destinationLocale |
string | No | en |
Target language |
*Either id or path must be provided.
After moving, the page URL changes. Update all external links pointing to the old path.
You: "I just finished developing the Ticket Merge Plugin.
Create a comprehensive technical wiki page."
Claude:
1. Analyzes the code in src/
2. Reads the README.md
3. Extracts API endpoints, classes, methods
4. Generates structured Markdown documentation
5. Creates wiki page via wikijs_create_page
You: "Add a section about performance optimization to the
Ticket Merge Plugin page."
Claude:
1. Retrieves current page via wikijs_get_page
2. Analyzes existing content
3. Generates new section
4. Updates page via wikijs_update_page
You: "Find all osTicket pages and move them under projects/osticket/"
Claude:
1. Searches via wikijs_search_pages for "osTicket"
2. Lists found pages
3. Moves each page via wikijs_move_page to new path
4. Provides summary
Symptom: Missing required environment variables: WIKIJS_API_URL, WIKIJS_API_TOKEN
Check:
~/.claude/mcp-servers/wikijs/.env exist?WIKIJS_API_URL and WIKIJS_API_TOKEN set?Solution:
cp .env.example ~/.claude/mcp-servers/wikijs/.env
# Edit file with correct values
Symptom: GraphQL Error: Forbidden
Check: Does the API token have the required permissions?
Solution:
read:pages, write:pages, manage:pagesSymptom: HTTP error! status: 404
Check: Is WIKIJS_API_URL correct?
Solution:
The URL must end with /graphql, e.g., https://your-wiki.com/graphql
Symptom: Server not listed in /mcp or status "failed"
Check:
~/.claude.json syntax (must be valid JSON)dist/index.js.env file existsSolution:
# Re-register
claude mcp add -s user wikijs node ~/.claude/mcp-servers/wikijs/dist/index.js
# Completely restart Claude Code
/exit
claude
Symptom: Server works in one project but not in others
Cause: Server was registered without -s user flag
Solution:
claude mcp add -s user wikijs node ~/.claude/mcp-servers/wikijs/dist/index.js
Symptom: Request times out
Check: Is the Wiki.js instance reachable and performant?
Solution: The API timeout is 30 seconds. For very large pages (>100k chars), content may be automatically truncated.
wikijs-mcp-server/
βββ src/
β βββ index.ts # MCP server entry point + tool registration
β βββ constants.ts # Configuration constants
β βββ types.ts # TypeScript type definitions
β βββ schemas/
β β βββ index.ts # Zod validation schemas for all tools
β βββ services/
β β βββ client.ts # WikiJsClient - GraphQL client
β β βββ error-handler.ts # Centralized error handling
β βββ tools/
β βββ index.ts # Tool exports
β βββ create-page.ts # wikijs_create_page
β βββ update-page.ts # wikijs_update_page (with auto-fetch)
β βββ get-page.ts # wikijs_get_page
β βββ list-pages.ts # wikijs_list_pages
β βββ search-pages.ts # wikijs_search_pages
β βββ delete-page.ts # wikijs_delete_page
β βββ move-page.ts # wikijs_move_page
βββ tests/
β βββ update-page.test.ts # Vitest unit tests
βββ dist/ # Compiled JavaScript (tsc)
βββ .github/workflows/
β βββ ci.yml # GitHub Actions CI
βββ package.json
βββ tsconfig.json
βββ vitest.config.ts
βββ .env.example
| Constant | Value | Description |
|---|---|---|
CHARACTER_LIMIT |
100,000 | Maximum content length before truncation |
DEFAULT_PAGE_LIMIT |
50 | Default pagination limit |
MAX_PAGE_LIMIT |
200 | Maximum pagination limit |
API_TIMEOUT |
30,000 ms | GraphQL request timeout |
Transport: stdio (standard MCP transport)
Protocol: MCP 1.0
API: Wiki.js GraphQL API with Bearer Token Authentication
Validation: Zod runtime schemas with descriptive error messages
| Technology | Purpose |
|---|---|
| TypeScript (strict mode) | Type-safe development |
| @modelcontextprotocol/sdk v1.24+ | MCP Server SDK with McpServer.tool() API |
| Zod | Runtime validation of all inputs |
| Vitest | Unit testing |
| dotenv | Environment variable loading |
destructiveHint: true on delete, readOnlyHint: true on read toolsWhat is MCP?
The Model Context Protocol (MCP) is an open protocol by Anthropic that enables AI assistants like Claude to interact with external tools and services. An MCP server provides tools (functions) that Claude can call during a conversation.
Which MCP clients are supported?
Any MCP-compatible client. Tested with Claude Desktop and Claude CLI (Claude Code).
Which Node.js version is required?
Node.js 18 or higher. The server uses ES Modules ("type": "module" in package.json).
Can I use the server without npm global install?
Yes, clone the repository and register the server with the path to dist/index.js.
Does content get lost on metadata-only updates?
No. On metadata-only updates (e.g., only changing isPublished), the server automatically fetches the existing content and sends it with the update. Content and tags are automatically preserved.
MIT License - See LICENSE