# WikiJS MCP Server A Model Context Protocol (MCP) server that provides integration with WikiJS, allowing AI assistants to search and retrieve content from your WikiJS knowledge base. ## Overview This MCP server enables AI assistants to interact with WikiJS instances by providing tools to: - Search for pages by query string - Retrieve pages by ID - Retrieve pages by path and locale - Get all pages from the wiki - Edit pages (when enabled) ## Installation ### Using npx (published package) ```bash # NOTE: the binary is named wikijs-mcp-edit, not after the package name: npx -p @cahaseler/wikijs-mcp wikijs-mcp-edit # pnpm equivalent (pnpx is a deprecated alias of pnpm dlx): pnpm dlx @cahaseler/wikijs-mcp wikijs-mcp-edit ``` This always runs the *latest published* version from npm. For the current feature branch (see git remote), build from source instead. ### From source ```bash git clone ssh://git@gogs.netdome.biz:10022/netdome/wikijs-mcp-server-cahaseler.git cd wikijs-mcp-server-cahaseler pnpm install # or: npm install pnpm run build # or: npm run build ``` ## Configuration ### Claude Code #### Method 1: Using the CLI (Recommended) ```bash # Add as a user-scoped server (available across all projects) claude mcp add wikijs \ -e WIKIJS_URL=https://your-wiki.example.com \ -e WIKIJS_API_KEY=your-api-key \ -- npx -p @cahaseler/wikijs-mcp wikijs-mcp-edit # Or, when running from a local clone (uses your build instead of the # published package): claude mcp add wikijs \ -e WIKIJS_URL=https://your-wiki.example.com \ -e WIKIJS_API_KEY=your-api-key \ -- node /absolute/path/to/wikijs-mcp/build/index.js # Or with edit functionality enabled claude mcp add wikijs \ -e WIKIJS_URL=https://your-wiki.example.com \ -e WIKIJS_API_KEY=your-api-key \ -e WIKIJS_ENABLE_EDIT=true \ -- npx -p @cahaseler/wikijs-mcp wikijs-mcp-edit ``` #### Method 2: Project-scoped configuration Create a `.mcp.json` file in your project root: ```json { "mcpServers": { "wikijs": { "command": "npx", "args": ["-p", "@cahaseler/wikijs-mcp", "wikijs-mcp-edit"], "env": { "WIKIJS_URL": "https://your-wiki.example.com", "WIKIJS_API_KEY": "your-api-key", "WIKIJS_ENABLE_EDIT": "false" } } } } ``` ### Cursor Add to your Cursor settings (`.cursor/settings.json`): ```json { "mcpServers": { "wikijs-mcp": { "command": "npx", "args": ["-p", "@cahaseler/wikijs-mcp", "wikijs-mcp-edit"], "env": { "WIKIJS_URL": "https://your-wiki.example.com", "WIKIJS_API_KEY": "your-api-key", "WIKIJS_ENABLE_EDIT": "false" } } } } ``` ### Claude Desktop Add to your Claude Desktop configuration: - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` - Linux: `~/.config/Claude/claude_desktop_config.json` ```json { "mcpServers": { "wikijs-mcp": { "command": "npx", "args": ["-p", "@cahaseler/wikijs-mcp", "wikijs-mcp-edit"], "env": { "WIKIJS_URL": "https://your-wiki.example.com", "WIKIJS_API_KEY": "your-api-key", "WIKIJS_ENABLE_EDIT": "false" } } } } ``` ## Getting a WikiJS API Key 1. Log into your WikiJS instance as an administrator 2. Go to **Administration** > **API Access** 3. Enable the API if not already enabled 4. Click **New API Key** 5. Give it a name (e.g., "MCP Server") 6. Select **Full Access** or configure specific permissions 7. Set an appropriate expiration date 8. Copy the generated key immediately (it won't be shown again) ## Environment Variables | Variable | Description | Required | Default | |----------|-------------|----------|---------| | `WIKIJS_URL` | URL of your WikiJS instance (without `/graphql`) | Yes | - | | `WIKIJS_API_KEY` | WikiJS API key | Yes | - | | `WIKIJS_ENABLE_EDIT` | Enable page editing functionality | No | false | | `WIKIJS_DEFAULT_LOCALE` | Locale used when building page URLs | No | en | | `WIKIJS_MCP_TRANSPORT` | `stdio` (client spawns the server) or `http` (Streamable HTTP listener; see below) | No | stdio | | `WIKIJS_MCP_HOST` | Bind address for the HTTP listener | **Yes when `WIKIJS_MCP_TRANSPORT=http`** — there is no default on purpose | - | | `WIKIJS_MCP_PORT` | Port for the HTTP listener | No | 3001 | | `WIKIJS_MCP_BEARER_TOKEN` | Bearer token protecting the HTTP listener | **Yes for non-loopback binds** (see below) | - | ## Streamable HTTP transport (container / server mode) Use stdio only when your MCP client spawns the server process itself. To run the server next to Wiki.js in a container (client connects over the network), use the Streamable HTTP transport (MCP spec compliant, stateful sessions): ```bash WIKIJS_URL=http://wiki:3000 WIKIJS_API_KEY=your-key \ WIKIJS_MCP_TRANSPORT=http WIKIJS_MCP_HOST=0.0.0.0 WIKIJS_MCP_PORT=3001 \ WIKIJS_MCP_BEARER_TOKEN=choose-a-long-random-token \ node build/index.js ``` Startup logs the exact listener: `WikiJS MCP server listening on http://0.0.0.0:3001/mcp`. Endpoints: `POST/GET/DELETE /mcp` (MCP Streamable HTTP), `GET /health` (liveness probe, no auth). HTTP clients connect to `http://:/mcp` and must send `Authorization: Bearer ` on every request. **Startup validation — the server refuses to start otherwise:** - `WIKIJS_MCP_TRANSPORT=http` without `WIKIJS_MCP_HOST` → exit - Non-loopback `WIKIJS_MCP_HOST` (e.g. `0.0.0.0`) without `WIKIJS_MCP_BEARER_TOKEN` → exit A token is optional **only** for loopback binds (`127.0.0.1`, `localhost`, `::1`). OpenCode remote-MCP config (`opencode.json`): ```json { "mcp": { "wikijs": { "type": "remote", "url": "http://wikijs-mcp:3001/mcp", "oauth": false, "headers": { "Authorization": "Bearer choose-a-long-random-token" } } } } ``` (`oauth: false` disables OpenCode's automatic OAuth discovery — the bearer token is passed explicitly via `headers` instead; secrets can also reference environment variables, e.g. `"Bearer {env:WIKIJS_MCP_BEARER_TOKEN}"`.) The CLI flag `--transport stdio|http` overrides `WIKIJS_MCP_TRANSPORT` (subject to the same host/token validation). ## Available Tools Once configured, the following tools will be available (10 read / 6 write): **Read (always available):** - **search_pages** - Search for pages by query string - Parameters: `query` (required), `path` (optional), `locale` (optional) - **get_page_by_id** - Retrieve a specific page by its ID (full page incl. rendered content) - Parameters: `id` (required) - **get_page_by_path** - Retrieve a page by its path and locale - Parameters: `path` (required), `locale` (required) - **get_all_pages** - List pages with optional filters - Parameters: `limit` (optional, max 500), `locale` (optional), `tags` (optional) - **get_page_history** - Revision history of a page - Parameters: `id` (required), `offsetPage` (optional), `offsetSize` (optional, max 200) - **get_page_version** - A specific revision of a page - Parameters: `pageId` (required), `versionId` (required) - **get_page_tree** - Page tree of the site - Parameters: `locale` (required), `mode` (optional, `FOLDERS`/`PAGES`/`ALL`, default `PAGES`), `path` (optional), `parent` (optional), `includeAncestors` (optional) - **list_tags** - List all tags - **search_tags** - Search tags - Parameters: `query` (required) - **get_page_links** - Link graph of all pages for a locale - Parameters: `locale` (required) **Write (only available when `WIKIJS_ENABLE_EDIT=true`):** - **create_page** - Create a new WikiJS page - Parameters: `title`, `content`, `description`, `path` (required); `editor` (default `markdown`), `isPublished` (default `true`), `isPrivate` (default `false`), `locale` (optional, default `en`), `tags` (optional) - **edit_page** - Edit a WikiJS page by its ID. **Full-document replace for `content`**; all other fields are optional — omitted fields keep their existing values (metadata is never wiped by omission) - Parameters: `id`, `content` (required); `title`, `description`, `path`, `editor`, `isPublished`, `isPrivate`, `locale`, `tags` (optional) - **move_page** - Move a page to a new path/locale - Parameters: `id`, `destinationPath`, `destinationLocale` (required) - **delete_page** - Delete a page - Parameters: `id` (required) - **restore_page_version** - Restore a previous version - Parameters: `pageId`, `versionId` (required) - **convert_page_editor** - Convert a page to another editor type - Parameters: `id`, `editor` (required e.g. `markdown`, `visual`) ## Development ### Prerequisites - Node.js 18+ at runtime for the built server (`engines` in package.json) - Node.js 20.19+ for development tooling (eslint 10 requires `^20.19 || ^22.13 || >=24`) - npm or pnpm - Docker (for local WikiJS testing) ### Setup 1. Clone the repository: ```bash git clone ssh://git@gogs.netdome.biz:10022/netdome/wikijs-mcp-server-cahaseler.git cd wikijs-mcp-server-cahaseler ``` 2. Install dependencies (pnpm primary, npm works too): ```bash pnpm install # or: npm install ``` 3. Copy the environment template: ```bash cp env.example .env ``` 4. Edit `.env` with your WikiJS credentials ### Local WikiJS Instance To run a local WikiJS instance for testing: ```bash # Start WikiJS and PostgreSQL (also brings up the mcp service — see below) docker compose up -d # Start only WikiJS and PostgreSQL: docker compose up -d db wiki # The instance will be available at http://localhost:3000 # Follow the setup wizard to create an admin account ``` The `mcp` service in `docker-compose.yml` runs the built server in HTTP mode next to the wiki instance: ```bash WIKIJS_MCP_BEARER_TOKEN=choose-a-long-random-token \ WIKIJS_API_KEY= \ docker compose up -d mcp # -> MCP listener on http://localhost:3001/mcp (port published 3001:3001) ``` ### Building ```bash pnpm run build # or: npm run build pnpm run clean # alternative: make clean # or via make (uses pnpm internally) make build ``` ### Testing the MCP Server The default transport is stdio — it is started *by* an MCP client, not manually as a daemon. For the HTTP listener see ["Streamable HTTP transport"](#streamable-http-transport-container--server-mode) above. ```bash # Quick smoke without a wiki connection: expect output = version from package.json node build/index.js --version # Run it manually in stdio mode (it then waits, silently, for MCP protocol frames on stdin): WIKIJS_URL=http://localhost:3000 WIKIJS_API_KEY=your-key node build/index.js # Same, but explicit about the transport flag: WIKIJS_URL=http://localhost:3000 WIKIJS_API_KEY=your-key node build/index.js --transport stdio # Run the HTTP listener locally (loopback, no token required): WIKIJS_URL=http://localhost:3000 WIKIJS_API_KEY=your-key \ WIKIJS_MCP_TRANSPORT=http WIKIJS_MCP_HOST=127.0.0.1 \ node build/index.js # -> WikiJS MCP server listening on http://127.0.0.1:3001/mcp # The built server auto-loads .env from the current working directory (dotenv), # so from the repo root this is sufficient: node build/index.js — provided # you created .env via the Setup steps above. Note: env variables take # precedence over .env values. # Interactive verify the tools without a full client setup (browser UI, default http://localhost:6274): npx @modelcontextprotocol/inspector node build/index.js # pnpm: pnpm dlx @modelcontextprotocol/inspector node build/index.js ``` Missing env vars abort the server immediately with `WIKIJS_URL and WIKIJS_API_KEY must be set` on stderr. HTTP mode aborts when `WIKIJS_MCP_HOST` is missing or a non-loopback bind has no `WIKIJS_MCP_BEARER_TOKEN`. ## Security Considerations - **API Key Storage**: Never commit your API key to version control - **Edit Permissions**: The edit functionality is disabled by default. Only enable it if you trust the environment where the MCP server is running - **Scope Permissions**: When creating the WikiJS API key, consider using the minimum required permissions instead of full access - **HTTP transport auth**: A non-loopback HTTP bind requires `WIKIJS_MCP_BEARER_TOKEN` — the server refuses to start otherwise. Even with a token, prefer exposing the listener only to the network segment that needs it (container network, not the host's public interfaces) - **HTTP transport token scope**: The bearer token protects the MCP endpoint itself; it is separate from the WikiJS API key ## Troubleshooting ### "WIKIJS_URL and WIKIJS_API_KEY must be set" Ensure your environment variables are properly configured. Check your `.env` file or the environment variables in your MCP client configuration. ### "Failed to update page: Unauthorized" Your API key may be expired or lack the necessary permissions. Create a new API key with appropriate permissions. ### `sh: wikijs-mcp-edit: not found` when running `npx @cahaseler/wikijs-mcp` npx fetched the package but looked for a binary named after the package. The binary is called `wikijs-mcp-edit`: ```bash npx -p @cahaseler/wikijs-mcp wikijs-mcp-edit ``` ### GraphQL errors during development If you modify the GraphQL queries, regenerate the types (requires `WIKIJS_URL` reachable — it introspects your Wiki.js instance): ```bash pnpm codegen # or: npm run codegen ``` ## Contributing 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## License This project is licensed under the MIT License - see the LICENSE file for details.