Skip to main content
Glama
MaxPopov
by MaxPopov

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)

Компоненты

Каталог

Что это

packages/wikijs-auth-module/

Кастомный модуль аутентификации для Wiki.js 2.5.x — проверяет RS256-утверждения, подписанные MCP-сервером, и возвращает нативный JWT Wiki.js (подробнее)

packages/mcp-server/

Удалённый MCP-сервер (Streamable HTTP): сервер авторизации OAuth 2.1 для MCP-клиентов поверх Google OIDC + брокер токенов + инструменты

packages/e2e-ui/

Только для тестов: браузерный UI e2e (Playwright) и автономный эмулятор фейкового Google IdP

deploy/docker-compose.dev.yml

Изолированный тестовый стенд (Wiki.js 2.5.303 + Postgres + ACL seed) — только для разработки/CI

deploy/docker-compose.e2e.yml

Полный стек UI e2e (фейковый IdP + Wiki.js + MCP + Playwright) — только для тестов

deploy/docker-compose.prod.yml

Продакшен-развёртывание: только MCP-сервер, указывающий на вашу существующую Wiki.js

deploy/seed/run.mjs

Точка входа для сидинга тестового стенда (seed.mjs — библиотека)

Related MCP server: Yandex Wiki MCP

Как это работает

  1. MCP-клиент подключается к https://mcp.agnostic.comparison/mcp и выполняет OAuth 2.1 (динамическая регистрация клиентов + PKCE). Google не поддерживает DCR, поэтому MCP-сервер сам является сервером авторизации для клиентов, а Google используется только для проверки личности человека. Токены Google никогда не покидают сервер; клиенты получают собственные непрозрачные (opaque) токены MCP-сервера. После входа через Google пользователь видит экран согласия, где указаны приложение и его redirect URI — это защита от «перепорученного посредника» (confused deputy), чтобы сторонний зарегистрированный клиент не мог получить токен пользователя без его ведома; согласие запоминается для каждого пользователя и клиента.

  2. Проверяется id_token от Google (подпись, iss, aud, email_verified, hd = ваш домен Workspace).

  3. Брокер токенов MCP-сервера обменивает идентичность Google на нативный JWT Wiki.js: он подписывает короткоживущее RS256-утверждение (TTL 60 секунд, уникальный jti) и вызывает стандартную GraphQL-мутацию authentication.login со стратегией mcpdelegation. Модуль Wiki.js проверяет утверждение, находит пользователя по почте и возвращает JWT через стандартный поток refreshToken(). JWT кэшируется и обновляется до истечения срока действия.

  4. Каждый вызов инструмента идёт в GraphQL Wiki.js с Authorization: Bearer <JWT пользователя>. Страницу, доступ к которой запрещён, невозможно прочитать или изменить, и она не появляется в поисковой выдаче или списках — это подтверждено e2e-тестами (матрица разрешить/запретить для двух пользователей в разных группах).

Инструменты

Инструмент

Описание

whoami

Личность пользователя + его группы и права в Wiki.js (диагностика доступа)

search_wiki

Полнотекстовый поиск; результаты фильтруются по правам пользователя

get_page

Страница по id или пути (метаданные + полный markdown)

list_many

Страницы, видимые пользователю (фильтр по префиксу пути)

create_page

Создать страницу (markdown)

update_page

Обновление: чтение-слияние-запись, неуказанные поля сохраняются

delete_page

Удаление (необратимо, Wiki.js требует delete:pages)


Интеграция с вашей 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:

Переменная

Значение

MCP_IMAGE

Тегированный образ (workflow Release on main автоматически публикует ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z, когда пушится изменение версии и вливаетесь в main, или соберите локально: docker build -f packages/mcp-server/Dockerfile -t wikijs-mcp-server:local .)

PUBLIC_URL

Публичный HTTPS URL MCP-сервера

WIKIJS_URL

URL вашей Wiki.js (внутренний предпочтителен)

WIKIJS_STRATEGY_KEY

Описание стратегии из шага 3 (mcpdelegation если вы дали такое имя)

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET

Из шага 4

GOOGLE_ALLOWED_DOMAIN

Домен вашего Workspace, например company.com — аккаунты вне домена отклоняются

Поставьте 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:

  1. «Кто я в вики?» — инструмент whoami должен показать вашу почту, группы и права из Wiki.js.

  2. Попросите найти/открыть страницу, к которой у вас есть доступ, — OK.

  3. Запросите страницу, на которую нет прав, — получите явный отказ («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

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.

  • Confluence MCP — wraps the Confluence Cloud REST API v2 (OAuth)

  • Google Docs MCP Pack — read, create, and edit Google Docs via OAuth.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MaxPopov/wikijs-mcp-google-auth'

If you have feedback or need assistance with the MCP directory API, please join our Discord server