wikijs-mcp-google-auth
wikijs-mcp-google-auth
MCP-слой поверх существующей Wiki.js 2.5.x: корпоративный пользователь входит через Google Workspace и работает с вики через LLM (claude.ai, Claude Desktop, любой MCP-клиент) — строго в рамках своих прав Wiki.js.
Главный принцип: Wiki.js — единственный источник правды для авторизации. У MCP-сервера нет собственных пользователей/групп/прав и нет глобального API-ключа. Каждая операция выполняется под собственным JWT конкретного пользователя Wiki.js, и именно Wiki.js решает, разрешить или запретить (Группы / Права / Правила страниц).
Google Workspace ──OAuth/OIDC──▶ MCP Server ──signed assertion──▶ Wiki.js
│ auth module "mcpdelegation"
│ → refreshToken() → native JWT
│
MCP client (claude.ai / Desktop) ◀──┴── tools: search / get / list /
create / update / delete / whoami
(all via GraphQL with the user's JWT)Компоненты
Каталог | Что это |
| Кастомный модуль аутентификации для Wiki.js 2.5.x — проверяет RS256-утверждения, подписанные MCP-сервером, и возвращает нативный JWT Wiki.js (подробнее) |
| Удалённый MCP-сервер (Streamable HTTP): сервер авторизации OAuth 2.1 для MCP-клиентов поверх Google OIDC + брокер токенов + инструменты |
| Только для тестов: браузерный UI e2e (Playwright) и автономный эмулятор фейкового Google IdP |
| Изолированный тестовый стенд (Wiki.js 2.5.303 + Postgres + ACL seed) — только для разработки/CI |
| Полный стек UI e2e (фейковый IdP + Wiki.js + MCP + Playwright) — только для тестов |
| Продакшен-развёртывание: только MCP-сервер, указывающий на вашу существующую Wiki.js |
| Точка входа для сидинга тестового стенда ( |
Related MCP server: wikijs-mcp
Как это работает
MCP-клиент подключается к
https://mcp.agnostic.comparison/mcpи выполняет OAuth 2.1 (динамическая регистрация клиентов + PKCE). Google не поддерживает DCR, поэтому MCP-сервер сам является сервером авторизации для клиентов, а Google используется только для проверки личности человека. Токены Google никогда не покидают сервер; клиенты получают собственные непрозрачные (opaque) токены MCP-сервера. После входа через Google пользователь видит экран согласия, где указаны приложение и его redirect URI — это защита от «перепорученного посредника» (confused deputy), чтобы сторонний зарегистрированный клиент не мог получить токен пользователя без его ведома; согласие запоминается для каждого пользователя и клиента.Проверяется
id_tokenот Google (подпись,iss,aud,email_verified,hd= ваш домен Workspace).Брокер токенов MCP-сервера обменивает идентичность Google на нативный JWT Wiki.js: он подписывает короткоживущее RS256-утверждение (TTL 60 секунд, уникальный
jti) и вызывает стандартную GraphQL-мутациюauthentication.loginсо стратегиейmcpdelegation. Модуль Wiki.js проверяет утверждение, находит пользователя по почте и возвращает JWT через стандартный потокrefreshToken(). JWT кэшируется и обновляется до истечения срока действия.Каждый вызов инструмента идёт в GraphQL Wiki.js с
Authorization: Bearer <JWT пользователя>. Страницу, доступ к которой запрещён, невозможно прочитать или изменить, и она не появляется в поисковой выдаче или списках — это подтверждено e2e-тестами (матрица разрешить/запретить для двух пользователей в разных группах).
Инструменты
Инструмент | Описание |
| Личность пользователя + его группы и права в Wiki.js (диагностика доступа) |
| Полнотекстовый поиск; результаты фильтруются по правам пользователя |
| Страница по id или пути (метаданные + полный markdown) |
| Страницы, видимые пользователю (фильтр по префиксу пути) |
| Создать страницу (markdown) |
| Обновление: чтение-слияние-запись, неуказанные поля сохраняются |
| Удаление (необратимо, Wiki.js требует |
Интеграция с вашей Wiki.js: пошагово
Вам понадобится: Wiki.js 2.5.x (тестировано на 2.5.303) с доступом к её файловой системе / Docker-конфигурации; хост для MCP-сервера с публичным HTTPS-эндпоинтом; доступ администратора к Google Cloud Console вашего Workspace.
Шаг 1. Установите проверочный модуль в Wiki.js
Docker: добавьте volume в сервис wiki и перезапустите контейнер:
services:
wiki:
image: ghcr.io/requarks/wiki:2.5.303
volumes:
- /opt/wikijs-mcp/wikijs-auth-module:/wiki/server/modules/authentication/mcpdelegation:ro(содержимое packages/wikijs-auth-module/ из этого репозитория помещается в /opt/wikijs-mcp/wikijs-auth-module; имя целевого каталога должно быть точно mcpdelegation)
Bare metal: скопируйте packages/wikijs-auth-module/ в <wiki>/server/modules/authentication/mcpdelegation/ и перезапустите Wiki.js.
После настройки (шаг 3) в логе Wiki.js будет видно:Authentication Strategy MCP Delegation: [ OK ].
Шаг 2. Сгенерируйте ключи для утверждений (assertion)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out mcp-assertion-key.pem
openssl pkey -in mcp-assertion-key.pem -pubout -out mcp-assertion-key.pub.pemПриватный ключ (mcp-assertion-key.pem) остаётся только на хосте MCP-сервера. На следующем шаге публичный ключ добавляется в Wiki.js.
Шаг 3. Настройте стратегию в панели администратора Wiki.js
Администрирование → Auth → Add Strategy → MCP Delegation:
Assertion Public Key (PEM) — содержимое файла
mcp-assertion-key.pub.pem;Expected Audience / Issuer — оставьте значения по умолчанию (
urn:wikijs:mcp-delegation/urn:wikijs-mcp-google-auth);User Lookup Provider Priority — порядок провайдеров для поиска пользователя по email. Если ваши пользователи входят через Google/OIDC, поставьте этого провайдера первым (принимаются и ключи модулей:
google,oidc,local);(необязательно) Self-registration + белый список доменов + автозачисление в указанные группы — чтобы новые пользователи Workspace автоматически создавались при первом запросе через MCP;
Сохраните.
Ключ стратегии отображается в списке (это WIKIJS_STRATEGY_KEY для MCP-сервера; если вы создавали стратегию вручную через UI, Wiki.js генерирует UUID — скопируйте его).
Учётные записи с включённой TFA нельзя использовать через делегирование — MCP-сервер вернёт понятную ошибку.
Шаг 4. Создайте Google OAuth-клиент
Google Cloud Console → APIs & Services → Credentials → Create credentials → Create OAuth client ID:
Тип приложения: Web application;
Authorized redirect URI:
https://mcp.company.com/oauth/google/callback(то есть вашPUBLIC_URL+/oauth/google/callback);Экран согласия OAuth: тип Internal (только ваш Workspace).
Сохраните Client ID и Client Secret.
Шаг 5. Разверните MCP-сервер
cd deploy
cp .env.example .env # fill in the values
mkdir -p keys && cp /path/to/mcp-assertion-key.pem keys/
chmod 644 keys/mcp-assertion-key.pem # the container runs as non-root node (uid 1000)
docker compose -f docker-compose.prod.yml up -dКонтейнер работает под непривилегированным пользователем
node— смонтированный файл ключа должен быть доступен ему для чтения (chmod 644); сам приватный ключ при этом защищён правами хостовой директорииkeys/.
Переменные .env:
Переменная | Значение |
| Тегированный образ (workflow |
| Публичный HTTPS URL MCP-сервера |
| URL вашей Wiki.js (внутренний предпочтителен) |
| Описание стратегии из шага 3 ( |
| Из шага 4 |
| Домен вашего Workspace, например |
Поставьте TLS-реверс-прокси перед портом 8000. Минимальный конфиг nginx:
server {
listen 443 ssl http2;
server_name mcp.company.com;
# ssl_certificate ...; ssl_certificate_key ...;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
proxy_buffering off; # streamable HTTP
}
}Проверка: curl https://mcp.company.com/healthz → {"ok":true};curl https://mcp.company.com/.well-known/oauth-authorization-server → метаданные OAuth.
Шаг 6. Подключение клиентов
claude.ai (Team/Enterprise): Settings → Connectors → Add custom connector → URL: https://mcp.company.com/mcp. При первом использовании клиент выполнит OAuth: регистрация клиента → вход в Google → готово.
Claude Desktop: Settings → Connectors → Add custom connector с тем же URL (или через mcp-remote для старых версий).
MCP Inspector (диагностика):npx @modelcontextprotocol/inspector → Transport: Streamable HTTP → URL https://mcp.company.com/mcp → Open Auth → пройдите поток.
Шаг 7. Проверка
В чате LLM:
«Кто я в вики?» — инструмент
whoamiдолжен показать вашу почту, группы и права из Wiki.js.Попросите найти/открыть страницу, к которой у вас есть доступ, — OK.
Запросите страницу, на которую нет прав, — получите явный отказ («Wiki.js denied this operation…»), и эта страница также отсутствует в результатах поиска/списка.
Локальная разработка
npm ci
npm run stand:up # Wiki.js 2.5.303 + Postgres (docker)
npm run stand:seed # finalize + groups/users/pages + strategy + dev keys
npm test # unit tests (auth module + OAuth provider)
npm run build && npm run e2e # in-process e2e: delegation, OAuth, tools — against a live stand
npm run stand:downТестовый стенд: admin@example.com/admin1234!, john@example.com (Engineering, без доступа к /management/*), kate@example.com (Management). Каждый внешний запрос (PR) запускает быстрые проверки (CI: lint + unit + build); тяжёлый docker e2e (e2e) и браузерные ui-e2e выполняются только на пушах в dev/main (т.е. перед merge), чтобы не замедлять итерации в PR.
Браузерный UI e2e (Playwright) под роли
Отдельный docker-стек deploy/docker-compose.e2e.yml поднимает эмулятор Google IdP (packages/e2e-ui/idpanton/ — страница входа с выбором роли вместо реального Google), Wiki.js, MCP-сервер и Playwright runner, который прогоняет весь браузерный OAuth+consent flow под разными ролями (John/Kate/out-of-domain). Эмулятор и Playwright поднимаются только в этом e2e-стеке — они никогда не попадают в prod/dev образы.
C=deploy/docker-compose.e2e.yml
docker compose -f $C build mcp
docker compose -f $C up -d db wiki idp # no --wait on wiki: the seed script is the readiness gate
docker compose -f $C run --rm seed
docker compose -f $C up -d --wait mcp
docker compose -f $C run --rm playwright # exit code = test result
docker compose -f $C down -vПроверяется: вход под ролью → на экране согласия указывается клиент → подтверждение → whoami и страницы в рамках роли (John не видит management/*, Kate видит); отказ → access_denied; аккаунт вне домена отклоняется до экрана согласия. Отдельный CI-воркфлоу (ui-e2e) делает это при пушах в dev/main.
Ручной запуск MCP-сервера для стенда:
PUBLIC_URL=http://localhost:8000 \
WIKIJS_URL=http://127.0.0.1:3000 \
MCP_ASSERTION_PRIVATE_KEY_FILE=deploy/keys/mcp-assertion-key.pem \
GOOGLE_CLIENT_ID=... GOOGLE_CLIENT_SECRET=... GOOGLE_ALLOWED_DOMAIN=example.com \
npm run dev -w @wikijs-mcp/serverРелизы
Релизы создаются автоматически. Обновите version в корневом package.json в dev, откройте PR из dev в main и смёржите его. Затем воркфлоу Release on main при пуше в main собирает и публикует ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z (а также :latest), создаёт git-тег vX.Y.Z и GitHub Release — всё в один запуск, используя только встроенный GITHUB_TOKEN (никакие PAT/секреты настраивать не нужно). Если версия не изменилась, запуск ничего не делает, поэтому обычные merge в main не создают релизов.
Разовые настройки репозитория для этого: Settings → Actions → General → Workflow permissions = Read and write permissions; а если вы защищаете теги ruleset-ом, разрешите GitHub Actions создавать теги
v*.
Заметки по безопасности
Assertion: RS256, TTL 60 сек, уникальный
jti, защита от повторного воспроизведения; приватный ключ живёт только на MCP-сервере. Компрометация ключа означает возможность войти под любым пользователем wiki — относитесь к нему как к корневому секрету и ротируйте его (новая пара ключей + обновление публичного ключа в стратегии).Google identity: канонический идентификатор —
iss+sub; email используется для поиска. Доменhdпроверяется по подписанному id_token, а не по параметрам.Защита от «запутанного посредника»: перед выдачей Authorization Code пользователь проходит через экран согласия для каждого клиента (может быть отключён через
requireConsentтолько для доверенного собственного клиента). Это предотвращает ситуацию, когда атакующий, зарегистрировавший собственный OAuth-клиент через DCR, незаметно получает токен жертвы.Rate limit Wiki.js:
authentication.login— 5 вызовов в минуту на IP, и все делегированные входы исходят с IP MCP-сервера. Брокер кэширует JWT (по умолчанию 30 минут) и при достижении лимита ждёт и повторяет, поэтому в обычной работе этого незаметно; при массовом подключении пользователей возможны задержки до минуты.Отзыв: стандартный OAuth
/revoke(на каждый токен); деактивация пользователя в Wiki.js разрывает делегирование при следующем обновлении JWT (≤30 мин); удалениеSESSION_STORE_FILEи перезапуск MCP-сервера завершают все сессии сразу.Аудит: каждый вызов инструмента логируется в структурированном виде (кто, какой инструмент, ок/отказ) без содержимого страниц.
MCP-эндпоинт: только Bearer-token, 120 запросов в минуту на токен, защитные заголовки; OAuth-эндпоинты защищены встроенным rate-лимитом SDK.
Ограничения
RAG/семантический поиск — отдельный будущий сервис. Точка подключения уже готова:
search_wikiработает через интерфейсSearchBackend(no— v1 = нативный поиск Wiki.js; RAG-сервис будет получать JWT пользователя Wiki.js и сохранит модель ACL). См.docs/rag-integration.md.Один экземпляр MCP-сервера (FileStore + replay-кэш в памяти). Для высокой доступности требуется общее хранилище (Redis) — интерфейс
KVStoreуже выделен.В Wiki.js 3.x другой механизм авторизации — модуль предназначен для 2.5.x.
Лицензия
Apache-2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
- hiveWikiOAuthai.hivewiki
Shared project wiki for AI agents: read and write pages, next actions, and activity logs over MCP.
- FlowdexOAuthdk.flowdex
Read and write your team's shared, AI-readable wiki from any MCP client.
Read-only MCP for the Eco game wiki: search, Markdown pages, and wiki_* lookups. No keys, no writes.
Hosted markdown project wikis your team's AI assistants read, search, and update over MCP.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables reading, creating, updating, and appending content to Yandex Wiki pages via MCP. Supports both read-write and read-only modes.730 PyPI9MIT
- AlicenseAqualityAmaintenanceEnables MCP clients to search, read, and edit Wiki.js pages, and manage assets, comments, users, groups, and maintenance jobs through the Wiki.js GraphQL API.6203MIT
- FlicenseNot gradedqualityBmaintenanceEnables MCP clients to interact with a Wiki.js 2.x instance via its GraphQL API, allowing page listing, reading, full-text search, creation, updating, and deletion, with a read-only mode and robust path handling.-
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to maintain a persistent Markdown knowledge base by ingesting sources, searching and reading notes, and creating or updating wiki pages with optimistic locking.12AGPL 3.0