# WikiJS MCP Server A [Model Context Protocol](https://modelcontextprotocol.io) server for [WikiJS](https://js.wiki). It lets MCP clients such as Claude Code, Claude Desktop, Cursor, or any custom agent search and read a WikiJS knowledge base, and optionally create or edit pages. This is a Go rewrite of [cahaseler/wikijs-mcp](https://github.com/cahaseler/wikijs-mcp). It has no Node.js runtime, no npm install step, and no GraphQL code generation; the result is a single static binary. ## Features - `search_pages`, `get_page_by_id`, `get_page_by_path`, and `get_all_pages` for reading a wiki. - `create_page` and `edit_page` when editing is explicitly enabled. - Absolute page URLs in every result. - **stdio** transport for local MCP clients. - **Streamable HTTP** transport with bearer-token authentication required for non-loopback binds. - Structured MCP output (`structuredContent`) plus JSON text for older clients. - Configuration through environment variables or an optional `.env` file; secrets never appear in flags. ## Requirements - Go 1.25 or newer to build. The result is a single binary with no runtime dependencies. - A WikiJS instance and an API key. In WikiJS, open **Administration → API Access**, enable the API, create a key, and copy it. Read access is enough for the four read tools; `create_page` and `edit_page` need write access. ## Build From the repository root: ```bash make build ``` The binary is written to `bin/wikijs-mcp`. You can also install it directly: ```bash go install ./cmd/wikijs-mcp ``` Set the required environment variables: ```bash export WIKIJS_URL=https://wiki.example.com export WIKIJS_API_KEY=your-api-key ``` `WIKIJS_URL` is the base URL of the wiki. A trailing slash or a `/graphql` suffix is accepted. ### Using a `.env` file The server loads `.env` from the current working directory automatically when the file exists. Variables that are already exported take precedence, so a shell environment can always override the file: ```bash cp env.example .env # edit .env ./bin/wikijs-mcp ``` To use a different file, pass `--env-file` or set `ENV_FILE`: ```bash ./bin/wikijs-mcp --env-file /etc/wikijs-mcp.env # or: ENV_FILE=/etc/wikijs-mcp.env ./bin/wikijs-mcp ``` Precedence for selecting the file: `--env-file` > `ENV_FILE` > `./.env`. Values from the process environment always win over values from any env file. A missing default `.env` is ignored; an explicitly selected file must exist and be readable. The file supports comments, `export KEY=value`, and quoted values. ## Use with the stdio transport The default transport is stdio. The MCP client starts the binary and communicates over stdin/stdout. ### Claude Code ```bash claude mcp add wikijs \ -e WIKIJS_URL=https://wiki.example.com \ -e WIKIJS_API_KEY=your-api-key \ -- /absolute/path/to/bin/wikijs-mcp ``` Add `-e WIKIJS_ENABLE_EDIT=true` to expose the page-editing tools. ### Claude Desktop and Cursor Add an entry to the client's MCP configuration: ```json { "mcpServers": { "wikijs": { "command": "/absolute/path/to/bin/wikijs-mcp", "env": { "WIKIJS_URL": "https://wiki.example.com", "WIKIJS_API_KEY": "your-api-key", "WIKIJS_ENABLE_EDIT": "false" } } } } ``` Typical configuration paths: - Claude Desktop (Linux): `~/.config/Claude/claude_desktop_config.json` - Claude Desktop (macOS): `~/Library/Application Support/Claude/claude_desktop_config.json` - Cursor: `~/.cursor/mcp.json` ### Generic stdio client Run the binary with the environment above. It logs to stderr and speaks MCP JSON-RPC on stdout, so it must be launched by an MCP client rather than used interactively. ## Use as an HTTP server Start the server with the Streamable HTTP transport: ```bash export WIKIJS_URL=https://wiki.example.com export WIKIJS_API_KEY=your-api-key export MCP_AUTH_TOKEN="$(openssl rand -hex 32)" ./bin/wikijs-mcp --transport http --addr :8080 --path /mcp ``` The MCP endpoint is `http://localhost:8080/mcp`. A liveness endpoint is available at `GET /healthz`; it is always reachable without a token. For local-only use, the default address is `127.0.0.1:8080`, so no token is needed: ```bash ./bin/wikijs-mcp --transport http ``` If `MCP_AUTH_TOKEN` is set, every MCP request must send: ``` Authorization: Bearer ``` Without `MCP_AUTH_TOKEN`, the server refuses to start when `--addr`/`MCP_ADDR` is not a loopback address (`:8080`, `0.0.0.0:8080`, or a LAN hostname). This prevents accidentally exposing the wiki to the network. Connect an MCP client: ```bash claude mcp add --transport http wikijs http://localhost:8080/mcp \ --header "Authorization: Bearer $MCP_AUTH_TOKEN" ``` You can also explore the server with the MCP Inspector: ```bash npx @modelcontextprotocol/inspector --url http://localhost:8080/mcp \ --header "Authorization: Bearer $MCP_AUTH_TOKEN" ``` ### Flags | Flag | Environment | Default | Description | |------|-------------|---------|-------------| | `--transport` | `MCP_TRANSPORT` | `stdio` | `stdio` or `http` | | `--addr` | `MCP_ADDR` | `127.0.0.1:8080` | Listen address for HTTP | | `--path` | `MCP_PATH` | `/mcp` | Path of the MCP endpoint | | `--stateless` | `MCP_STATELESS` | `false` | Disable MCP sessions (useful behind load balancers) | | `--log-level` | `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, or `error` | | `--env-file` | `ENV_FILE` | `.env` | Env file to load (existing environment wins) | Notes for deployments: - By default the server uses stateful MCP sessions with a 30-minute idle timeout. Use `--stateless` if requests may hit different replicas. - A reverse proxy in front of the server must support streaming responses and must not buffer them (SSE). - The default listen address is loopback-only. To listen on all interfaces, set `--addr :8080` and provide `MCP_AUTH_TOKEN`. - HTTP transport does not terminate TLS. Put it behind a TLS reverse proxy for remote access. ## Configuration | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `WIKIJS_URL` | yes | – | Base URL of the WikiJS instance | | `WIKIJS_API_KEY` | yes | – | WikiJS API key, sent as a bearer token | | `WIKIJS_ENABLE_EDIT` | no | `false` | Expose `create_page` and `edit_page` | | `WIKIJS_TIMEOUT` | no | `30s` | Timeout for one GraphQL request | | `MCP_TRANSPORT` | no | `stdio` | `stdio` or `http` | | `MCP_ADDR` | no | `127.0.0.1:8080` | HTTP listen address | | `MCP_PATH` | no | `/mcp` | HTTP endpoint path | | `MCP_STATELESS` | no | `false` | Disable HTTP sessions | | `MCP_AUTH_TOKEN` | no | – | Bearer token for HTTP; required when `MCP_ADDR` is not loopback | | `LOG_LEVEL` | no | `info` | Log verbosity; logs always go to stderr | | `ENV_FILE` | no | `.env` | Alternative env file; `--env-file` overrides it | ## Tools The four read tools are always available. Editing is disabled by default; set `WIKIJS_ENABLE_EDIT=true` to also expose the write tools. | Tool | Arguments | Description | |------|-----------|-------------| | `search_pages` | `query` (required), `path`, `locale` | Full-text search. Returns `results`, `suggestions`, and `totalHits`. | | `get_page_by_id` | `id` (required) | Full page by numeric ID, or `null`. | | `get_page_by_path` | `path`, `locale` (both required) | Full page by path and locale, or `null`. | | `get_all_pages` | `limit`, `locale`, `tags` | List pages with optional filters. Returns `{"pages": [...]}`. | | `create_page` | `title`, `content`, `description`, `path` (required); `editor`, `isPublished`, `isPrivate`, `locale`, `tags` | Create a page. | | `edit_page` | `id`, `title`, `content`, `description`, `path` (required); `editor`, `isPublished`, `isPrivate`, `locale`, `tags` | Update a page. | Defaults for the write tools: `editor=markdown`, `isPublished=true`, `isPrivate=false`, `locale=en`, `tags=[]`. Locales use the form `en` or `de-DE` (two lowercase letters, optionally followed by a hyphen and two uppercase letters). Every page result includes a `url` built from `WIKIJS_URL`; the locale is part of the URL for non-English pages. ## Local WikiJS for development ```bash docker compose up -d ``` WikiJS is then available at . Complete the setup wizard, create an API key under **Administration → API Access**, set `WIKIJS_URL` and `WIKIJS_API_KEY`, and run the server. ## Development ```bash make test # unit tests make test-race # unit tests with the race detector make vet # go vet make check # vet + race tests make run-http # run the HTTP transport on 127.0.0.1:8080 ``` Tests cover the GraphQL client against an `httptest` server, all tool handlers through an in-memory MCP session, and the HTTP transport including bearer-token authentication. See [AGENTS.md](AGENTS.md) for the code layout and conventions. ## Security - Keep `WIKIJS_API_KEY` and `MCP_AUTH_TOKEN` out of version control. Prefer the environment or a secrets manager over committing `.env`; keep the file mode restrictive (`chmod 600 .env`). - Editing is disabled by default. Enable it only for clients and environments you trust. - The HTTP transport refuses non-loopback addresses unless `MCP_AUTH_TOKEN` is set. Even with a token, use TLS (for example via a reverse proxy) before exposing it to untrusted networks. - The server never logs API keys, bearer tokens, or request bodies. ## License GPL-3.0-or-later. See [LICENSE](LICENSE).