Skip to main content
Glama
README.md
# outline-wiki-mcp

A stateless MCP server that turns your self-hosted [Outline](https://www.getoutline.com/) wiki into your AI team's knowledge base. No server-side credentials: every client sends its own Outline API token in the `Authorization` header, so AI permissions are exactly that user's wiki permissions — nobody can make their AI read a collection they can't see themselves. Ships 12 workflow tools covering search, read, write and organize — including `get_project_context`, which pulls a whole project bundle in one call — plus a draft→publish flow and an idempotent ClickUp → Outline migration CLI.

## Features

- **Per-user permissions, zero shared tokens** — the server keeps no credentials; the Outline API token in the request header is the identity.
- **12 tools**: search, doc tree, full-doc read, create/update/publish/archive, collections, move, file attachments.
- **`get_project_context`** — hand an agent everything about a project (all docs in the collection) in a single call.
- **Draft-first publishing** — `create_doc` writes drafts; `publish_doc` promotes them. AI edits stay reviewable before they land.
- **Document metadata headers** — docs carry a visible `kaynak / durum / son kontrol` (source / status / last-checked) blockquote that write tools parse and keep up to date.
- **Turkish-aware name matching** — collection lookup is case- and locale-correct (`İ`/`i`), single substring hits resolve, ambiguous ones refuse to guess.
- **DNS-rebinding protection** — Host allowlist on the MCP endpoint, configurable via `MCP_ALLOWED_HOSTS`.
- **Migration CLI** — ClickUp v3 Docs → Outline (doc = collection, page = document), idempotent via a mapping file, paced against Outline rate limits.
- **Small and boring on purpose** — one Dockerfile, non-root user, digest-pinned base image, runs as one service in the compose stack.

## Quickstart

```bash
cp docker-compose.example.yml docker-compose.yml
cp .env.example .env        # fill in SECRET_KEY, UTILS_SECRET, POSTGRES_PASSWORD, Google OAuth
docker compose up -d --build
```

The stack exposes nothing to the internet by itself — put a reverse proxy or tunnel in front (see the comments in `docker-compose.example.yml`).

Then create a personal API token in Outline (**profile → Settings → API Keys** — never share tokens) and point your MCP client at the server:

```json
{
  "mcpServers": {
    "wiki": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer <your-outline-api-token>" }
    }
  }
}
```

Add `.mcp.json` to your project's `.gitignore` — the token must never reach git.

## Tools

| Tool | What it does |
|---|---|
| `list_collections` | List all collections (projects/categories) with doc counts |
| `list_docs` | Document tree of one collection |
| `get_doc` | Full markdown + metadata of a doc, by title or id (drafts by id only) |
| `search` | Full-text search across the whole wiki |
| `get_project_context` | Entire project bundle — every doc in a collection, one call |
| `create_doc` | Create a doc (draft by default), metadata header generated automatically |
| `update_doc` | Replace or append content and refresh the metadata header |
| `publish_doc` | Publish a draft into its collection |
| `archive_doc` | Archive a doc (never deletes) |
| `create_collection` | Create a new project/category collection |
| `move_doc` | Move a doc to another collection or under another parent doc |
| `attach_file` | Upload a file (base64, 20 MB cap) and link it into a doc |

## ClickUp migration

Idempotent: keeps a mapping file (`migrate_mapping.json` by default) and resumes where it stopped. Each ClickUp doc becomes a collection, each page a document.

```bash
OUTLINE_API_URL=https://wiki.example.com/api OUTLINE_TOKEN=<outline-token> \
  python -m wiki_mcp.migrate \
    --clickup-token <pk_...> \
    [--workspace <clickup-workspace-id>] \
    [--only <substring-filter>] \
    [--mapping migrate_mapping.json]
```

## Development

```bash
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest -q
```

Tests run against an in-process fake Outline client — no live wiki needed.

## License

MIT — see [LICENSE](LICENSE).