## Zuwiki MCP

[Zuwiki](https://zuwiki.com), a product by [The Zu Company](https://thezucompany.com), is a platform for writing and publishing documentation: public product docs on your own domain, API references, changelogs and internal knowledge wikis for your team.

This package is a [Model Context Protocol](https://modelcontextprotocol.io) server for Zuwiki. Once connected to any MCP client (Claude, Cursor, Windsurf, VS Code, Zed, and more), your assistant can browse and edit your wikis, categories and pages in natural language.

### Quick start

You do not need to clone anything. All you need is Node.js 20+ installed. The server runs over stdio with the command:

```bash
npx -y @zuwiki/mcp
```

Most MCP clients use the same JSON config format, just in different places. On the first start a browser window opens, you sign in to Zuwiki, and you are ready to go.

#### Claude Code

```bash
claude mcp add zuwiki -- npx -y @zuwiki/mcp
```

#### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, equivalent on other OSes:

```json
{
  "mcpServers": {
    "zuwiki": {
      "command": "npx",
      "args": ["-y", "@zuwiki/mcp"]
    }
  }
}
```

#### Cursor

`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project):

```json
{
  "mcpServers": {
    "zuwiki": {
      "command": "npx",
      "args": ["-y", "@zuwiki/mcp"]
    }
  }
}
```

#### Windsurf

`~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "zuwiki": {
      "command": "npx",
      "args": ["-y", "@zuwiki/mcp"]
    }
  }
}
```

#### VS Code (Continue, Cline, or other MCP enabled extensions)

Add a server entry pointing to the same `npx -y @zuwiki/mcp` command. The exact location depends on the extension; the value is always the same.

#### Any other MCP client

Anything that can launch a stdio MCP server works. Configure it with:

* command: `npx`
* args: `["-y", "@zuwiki/mcp"]`

Or, if you have installed the package globally with `npm install -g @zuwiki/mcp`:

* command: `zuwiki-mcp`
* args: `[]`

### Example prompts

Once connected, try things like:

* "List my Zuwiki organizations and switch to the one called Acme."
* "Show me all wikis in the active organization."
* "Create a new page called 'Onboarding' in the wiki 'Handbook' with a short welcome text."
* "Find the deployment page and rewrite the section on staging."

### Organizations

Zuwiki accounts can belong to several organizations and every API request needs to pick one. Easiest way: ask the LLM to call `zuwiki_list_organizations` and then `zuwiki_set_active_organization`. The choice persists for the lifetime of the server. Alternatively set `ZUWIKI_ORGANIZATION_ID` in your MCP config.

### How authentication works

The server uses OAuth 2.1 (Authorization Code Flow with PKCE) against the Zuwiki auth server, with Dynamic Client Registration per RFC 7591 on first start. Access and refresh tokens are stored in `~/.config/zuwiki-mcp/credentials.json` with file mode 0600. Subsequent runs use the refresh token automatically without any user interaction.

To sign in as a different user, or to force a fresh authorization, delete that file.

### Available tools

Read tools:

* `zuwiki_list_organizations`, `zuwiki_get_active_organization`
* `zuwiki_list_wikis`, `zuwiki_list_all_wikis`, `zuwiki_get_wiki`, `zuwiki_get_wiki_editor`
* `zuwiki_list_subwikis`
* `zuwiki_search`
* `zuwiki_get_page_content`, `zuwiki_get_page_settings`, `zuwiki_get_page_history`

Write tools:

* `zuwiki_set_active_organization`
* `zuwiki_create_wiki`, `zuwiki_update_wiki`, `zuwiki_delete_wiki`
* `zuwiki_create_subwiki`, `zuwiki_update_subwiki`, `zuwiki_delete_subwiki`
* `zuwiki_create_category`, `zuwiki_rename_category`, `zuwiki_delete_category`
* `zuwiki_create_page`, `zuwiki_rename_page`, `zuwiki_delete_page`
* `zuwiki_update_page_content`, `zuwiki_update_page_settings`
* `zuwiki_set_page_status`, `zuwiki_restore_page_history`
* `zuwiki_move_page`, `zuwiki_reorder_items`, `zuwiki_apply_editor_order`

### Subwikis

A wiki is made up of one or more subwikis: a normal `WIKI` section (categories, pages and links), an `API` reference, a `CHANGELOG`, or a `REDIRECT` to an external URL. Exactly one subwiki is the default, served at the wiki root. List them with `zuwiki_list_subwikis`.

The content tools (`zuwiki_get_wiki_editor`, `zuwiki_create_category`, `zuwiki_create_page`, `zuwiki_move_page`, `zuwiki_reorder_items`, `zuwiki_apply_editor_order`) accept an optional `subwikiId`. When omitted they operate on the wiki's default subwiki, so existing usage keeps working unchanged; pass a `subwikiId` to read or edit a specific subwiki.

On failure each tool returns an `isError: true` result with a descriptive message. Common codes are `insufficient_scope`, `forbidden_or_not_member`, `not_found`, `conflict`, `rate_limited`. 429 responses are retried up to twice with backoff; 401 triggers an automatic token refresh and one retry.

### Configuration

CLI options:

```
--http                   Use streamable HTTP transport instead of stdio
--host <host>            HTTP host (default 127.0.0.1)
--port <port>            HTTP port (default 3333)
--path <path>            HTTP path (default /mcp)
--base-url <url>         Zuwiki base URL (default https://zuwiki.com)
--organization <id>      Active organization id
--credentials <path>     Path to the credentials file
--organizations-path <p> Override the API path for the organizations list
--help                   Show help
```

All options can also be set via environment variables. CLI flags take precedence:

```
ZUWIKI_BASE_URL            Zuwiki base URL
ZUWIKI_ORGANIZATION_ID     Active organization id
ZUWIKI_CREDENTIALS_PATH    Path to the credentials file
ZUWIKI_HTTP_HOST           HTTP host
ZUWIKI_HTTP_PORT           HTTP port
ZUWIKI_HTTP_PATH           HTTP path
ZUWIKI_ORGANIZATIONS_PATH  Override the API path for organizations
```

### Run from source

If you want to hack on the server itself:

```bash
pnpm install
pnpm build
node dist/cli.js
```

For development without rebuilding each time:

```bash
pnpm dev
```

### HTTP mode

```bash
node dist/cli.js --http --port 3333
```

The streamable HTTP endpoint listens at `http://127.0.0.1:3333/mcp`. Every client must send its own bearer token via the `Authorization` header on every request. The server forwards that token as is when talking to the Zuwiki API and never persists it. Valid tokens come from the Zuwiki auth server, for example via a client side OAuth flow.

### Tests

```bash
pnpm test
```

The tests cover PKCE generation, token refresh logic, HTTP behavior (401 retry, 429 backoff, scope and org errors) and MCP tool registration plus argument validation.

### Security

* Tokens are stored with mode 0600
* PKCE S256 is mandatory
* The state parameter is validated against CSRF
* In HTTP mode the server only forwards incoming bearer tokens and never persists them

### License

MIT. Zuwiki is built and maintained by [The Zu Company](https://thezucompany.com).
