Skip to main content
Glama
MaxPopov
by MaxPopov

wikijs-mcp-google-auth

Ein MCP-Layer auf Basis einer bestehenden Wiki.js 2.5.x: Ein Unternehmensbenutzer meldet sich mit Google Workspace an und arbeitet über ein LLM (claude.ai, Claude Desktop, beliebiger MCP-Client) mit dem Wiki — streng innerhalb seiner eigenen Wiki.js-Berechtigungen.

Kernprinzip: Wiki.js ist die einzige Quelle der Wahrheit für die Autorisierung. Der MCP-Server hat keine eigenen Benutzer/Gruppen/Berechtigungen und keinen globalen API-Schlüssel. Jede Operation läuft unter dem nativen Wiki.js-JWT des jeweiligen Benutzers, und Wiki.js selbst entscheidet über Erlauben/Verweigern (Gruppen / Berechtigungen / Seitenregeln).

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)

Komponenten

Verzeichnis

Beschreibung

packages/wikijs-auth-module/

Eigenes Authentifizierungsmodul für Wiki.js 2.5.x — prüft RS256-Assertions, die vom MCP-Server signiert wurden, und gibt ein natives Wiki.js-JWT zurück (Details)

packages/mcp-server/

Entfernter MCP-Server (Streamable HTTP): ein OAuth-2.1-Autorisierungsserver für MCP-Clients auf Basis von Google OIDC + Token-Broker + Tools

packages/e2e-ui/

Nur für Tests: Browser-UI-E2E (Playwright) und ein eigenständiger Fake-Google-IdP-Emulator

deploy/docker-compose.dev.yml

Isolierter Teststand (Wiki.js 2.5.303 + Postgres + ACL-Seed) — nur für Entwicklung/CI

deploy/docker-compose.e2e.yml

Vollständiger UI-E2E-Stack (Fake-IdP + Wiki.js + MCP + Playwright) — nur für Tests

deploy/docker-compose.prod.yml

Produktions-Deployment: nur der MCP-Server, der auf Ihre bestehende Wiki.js zeigt

deploy/seed/run.mjs

Einstiegspunkt zum Befüllen des Teststands (seed.mjs ist die Bibliothek)

Related MCP server: Yandex Wiki MCP

So funktioniert es

  1. Der MCP-Client verbindet sich mit https://mcp.company.com/mcp und führt OAuth-Lauf 2.1 durch (Dynamic Client Registration + PKCE). Google unterstützt kein DCR, daher ist der MCP-Server selbst der Autorisierungsserver für die Clients, und Google wird nur zur Authentifizierung des Menschen verwendet. Google-Tokens verlassen den Server nie; die Clients erhalten die eigenen opaken Tokens des MCP-Servers. Nach dem Google-Login sieht der Benutzer einen Zustimmungsbildschirm, der die Anwendung und ihre Redirect-URI nennt — eine Verteidigungsmaßnahme gegen das Confused-Deputy-Problem (damit ein registrierter Drittanbieter-Client den Token des Benutzers nicht ohne dessen Wissen erhalten kann); die Zustimmung wird pro Benutzer und pro Client gespeichert.

  2. Das id_token von Google wird verifiziert (Signatur, iss, aud, email_verified, hd = Ihre Workspace-Domain).

  3. Der Token-Broker des MCP-Servers tauscht die Google-Identität gegen ein Wiki-JWT: Er signiert eine kurzlebige RS256-Assertion (TTL 60 s, eindeutiges jti) und ruft mit der Standardmutation GraphQL authentication.login die Strategie mcpdelegation auf. Das Wiki.js-Modul prüft die Assertion, ermittelt den Benutzer anhand der E-Mail und gibt über den Standard-Flow refreshToken() ein JWT zurück. Das JWT wird gecacht und vor seinem Ablauf erneuert.

  4. Jeder Tool-Aufruf erfolgt mit Authorization: Bearer <user's JWT> an die Wiki.js-GraphQL-API. Eine nicht erlaubte Seite kann weder gelesen noch verändert werden und erscheint nicht in der Suche oder in Listen — durch E2E-Tests verifiziert (Erlaubt/Verweigert-Matrix für zwei Benutzer in verschiedenen Gruppen).

Tools

Tool

Beschreibung

whoami

Die Identität des Benutzers + dessen Wiki.js-Gruppen und -Berechtigungen (Zugriffsdiagnose)

search_wiki

Volltextsuche; Ergebnisse werden anhand der Benutzerrechte gefiltert

get_page

Eine Seite per ID oder geben Sie den Pfad (Metadaten + vollständiges Markdown)

list_pages

Für den Benutzer sichtbare Seiten (Filterung nach Pfad-Präfix)

create_page

Seite erstellen (Markdown)

update_page

Aktualisieren: Lesen-Zusammenführen-Schreiben; nicht angegebene Felder bleiben erhalten

delete_page

Löschen (destruktiv; Wiki.js erzwingt delete:pages)


Integration in Ihre eigene Wiki.js: Schritt für Schritt

Sie benötigen: Wiki.js 2.5.x (getestet mit 2.5.303) mit Zugriff auf das Dateisystem bzw. die Docker-Konfiguration; einen Host für den MCP-Server mit einem öffentlichen HTTPS-Endpunkt; Administratorzugriff auf die Google Cloud Console Ihres Workspace.

Schritt 1: Auth-Modul in Wiki.js installieren

Docker: Fügen Sie dem Wiki-Dienst ein Volume hinzu und starten Sie den Container neu:

services:
  wiki:
    image: ghcr.io/requarks/wiki:2.5.303
    volumes:
      - /opt/wikijs-mcp/wikijs-auth-module:/wiki/server/modules/authentication/mcpdelegation:ro

(Der Inhalt von packages/wikijs-auth-module/ aus diesem Repository wird nach /opt/wikijs-mcp/wikijs-auth-module gelegt; der Zielordnername muss exakt mcpdelegation lauten.)

Bare Metal: Kopieren Sie packages/wikijs-auth-module/ nach <wiki>/server/modules/authentication/mcpdelegation/ und starten Sie Wiki.js neu.

Nach der Konfiguration (Schritt 3) erscheint im Wiki.js-Log: Authentication Strategy MCP Delegation: [ OK ].

Schritt 2: Assert-Schlüssel generieren

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

Der private Schlüssel (mcp-assertion-key.pem) bleibt nur auf dem MCP-Server-Host. Der öffentliche Schlüssel wird im nächsten Schritt in Wiki.js eingetragen.

Schritt 3: Strategie in der Wiki.js-Administration konfigurieren

Administration → Auth → Strategie hinzufügen → MCP-Delegation:

  • Assertion Public Key (PEM) — den Inhalt von mcp-assertion-key.pub.pem;

  • Expected Audience / Issuer — die Standardwerte beibehalten (urn:wikijs:mcp-delegation / urn:wikijs-mcp-google-auth);

  • User Lookup Provider Priority — die Reihenfolge der Provider, über die der Benutzer anhand seiner E-Mail gefunden wird. Wenn Ihre Leute über Google/OIDC im Wiki anmelden, diesen Provider an die erste Stelle setzen (Modul-Keys sind ebenfalls zulässig: google, oidc, local);

  • (optional) Self-Registration + Domain-Whitelist + Auto-Enrollment-Gruppen — damit neue Workspace-Nutzer bei ihrer ersten MCP-Anfrage automatisch angelegt werden;

  • Speichern.

Der Strategie-Instanzschlüssel wird in der Liste angezeigt (dies ist für den MCP-Server der WIKIJS_STRATEGY_KEY; wenn Sie die Strategie manuell über die Oberfläche erstellt haben, erzeugt Wiki.js eine UUID — kopieren Sie diese).

Konten mit aktiviertem TFA können nicht über Delegation verwendet werden — der MCP-Server liefert eine klare Fehlermeldung.

Schritt 4: Google-OAuth-Client erstellen

Google Cloud Console → APIs und Dienste → Anmeldedaten → Anmeldedaten erstellen → OAuth-Client-ID.

  • Anwendungstyp: Webanwendung;

  • Autorisierte Weiterleitungs-URI: https://mcp.company.com/oauth/google/callback (Ihre PUBLIC_URL + /oauth/google/callback);

  • OAuth-Zustimmungsbildschirm: Typ Intern (nur Ihr Workspace).

Speichern Sie die Client-ID und das Client-Secret.

Schritt 5: MCP-Server bereitstellen

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

Der Container läuft als Nicht-Root-Benutzer node — die eingehängte Schlüsseldatei muss für ihn lesbar sein (chmod 644); der private Schlüssel selbst bleibt durch die Berechtigungen des Host-Verzeichnisses keys/ geschützt.

.env-Variablen:

Variable

Wert

MCP_IMAGE

Getagtes Image (der Workflow Release on main veröffentlicht automatisch ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z, wenn ein Versionsbump nach main gemergt wird; oder lokal bauen: docker build -f packages/mcp-server/Dockerfile -t wikijs-mcp-server:local .)

PUBLIC_URL

Die öffentliche HTTPS-URL des MCP-Servers

WIKIJS_URL

Die URL Ihrer Wiki.js (intern bevorzugt)

WIKIJS_STRATEGY_KEY

Der Strategie-Instanzschlüssel aus Schritt 3 (mcpdelegation, falls Sie ihn so benannt haben)

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET

Aus Schritt 4

GOOGLE_ALLOWED_DOMAIN

Ihre Workspace-Domain, z. B. company.com — Konten außerhalb werden abgelehnt

Stellen Sie einen TLS-Reverse-Proxy vor Port 8000. Minimal 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
  }
}

Prüfen: curl https://mcp.company.com/healthz{"ok":true}; curl https://mcp.company.com/.well-known/oauth-authorization-server → OAuth-Metadaten.

Schritt 6: Clients verbinden

claude.ai (Team/Enterprise): Einstellungen → Connectors → Benutzerdefinierten Connector hinzufügen → URL: https://mcp.company.com/mcp. Beim ersten Einsatz macht der Client folgende Aktionen: Client-Registrierung → Google-Login --> fertig.

Claude Desktop: Einstellungen → Connectors → Benutzerdefinierten Connector hinzufügen (mit derselben URL) (oder über mcp-remote für ältere Versionen).

MCP Inspector (Diagnose): npx @modelcontextprotocol/inspector → Transport: Streamable HTTP → URL https://mcp.company.com/mcp → Open Auth → Flow durchspielen.

Schritt 7: Prüfen

Im LLM-Chat:

  1. „Who am I in Wiki?“ → whoami sollte Ihre E-Mail, Gruppen und Berechtigungen aus Wiki-js zeigen.

  2. Bitten Sie danach, eine Seite zu finden/zu öffnen, auf die Sie Zugriff haben → OK.

  3. Bitten Sie eine Seite an, für die Sie keine Rechte haben → klare Ablehnung („Wiki.js hat diesen Vorgang abgelehnt …“), und diese Seite fehlt auch nicht in Suche und Anzeige.


Lokale Entwicklung

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

Teststand: admin@example.com/admin1234!, john@example.com (Engineering, kein Zugriff auf /admin), weil kate@example.com (Management). Jeder PR läuft durch die schnellen Checkpins (CI: Lint + Unit + Build); das schwere Docker-E2E (e2e) und das Browser-ui-e2e laufen nur bei Pushes auf dev/main (also vor dem Merge), damit PR-Iterationen nicht verlangsamt werden.

Browser-UI-E2E (Playwright) mit Rollen

Ein separater Docker-Stack deploy/docker-compose.e2e.yml bringt einen Fake-Google-IdP-Emulator (packages/e2e-ui/idp/ — eine Anmeldeseite mit Rollenauswahl statt echtem Google), Wiki.js, den MCP-Server und einen Playwright-Runner hoch, der den gesamten Browser-OAuth-/Consent-Flow unter verschiedenen Rollen durchläuft (John/Kate/outside-Domain). Emulator und Playwright kommen nur in diesem E2E-Stack vor — sie landen nie in den Produktions-/Dev-Images.

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

Es prüft: Anmeldung als Rolle → der Zustimmungsbildschirm nennt den Client → Genehmigen → whoami und die auf die Rolle eingeschränkten Seiten (John kann management/* nicht sehen, Kate schon); Ablehnen → access_denied; ein Konto außerhalb der Domäne wird vor der Zustimmung abgewiesen. Ein separater CI-Workflow (ui-e2e) erledigt das bei Pushes auf dev/main.

Den MCP-Server manuell gegen den Teststand ausführen:

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

Releases

Releases erfolgen automatisch. Erhöhe die version in der Root-package.json auf dev, öffne einen devmain-PR und merge ihn. Der Workflow Release on main baut und pusht bei dem beiden Push auf main das Image ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z (+ :latest) und erstellt den Git-Tag vX.Y.Z sowie ein GitHub-Release – alles in einem einzigen Workflow-Lauf, und zwar nur mit dem eingebauten GITHUB_TOKEN (kein PAT/Secret zu konfigurieren). Wenn die Version unverändert ist, ist der Lauf ein No-op, sodass gewöhnliche Merges auf main keine Releases erzeugen.

Einmalige Repository-Einstellungen dafür: Settings → Actions → General → Workflow permissions = Read and write permissions; und falls du Tags mit einem Ruleset schützst, erlaube GitHub Actions, v*-Tags zu erstellen.

Sicherheitshinweise

  • Assertion: RS256, TTL 60 s, eindeutige jti, Replay-Schutz; der private Schlüssel liegt ausschließlich auf dem MCP-Server. Ein kompromittierter Schlüssel bedeutet, dass man sich als beliebiger Wiki-Benutzer anmelden kann – behandle ihn also wie ein Root-Geheimnis und rotiere ihn (neues Schlüsselpaar erzeugen und den öffentlichen Schlüssel in der der Strategie aktualisieren).

  • Google-Identität: Der kanonische Identifikator ist iss+sub; die E-Mail dient zur Nachschlagen. Die hd-Domäne wird aus dem signierten id_token verifiziert, nicht aus Parametern.

  • Confused-Deputy-Schutz: Bevor ein Autorisierungscode ausgegeben wird, muss der Benutzer einen eine, auf den jeweiligen Client zugeschnittenen Zustimmungsbildschirm durchlaufen (kann nur für ein vertrauenswürdiges First-Party-Szenario über requireConsent deaktiviert werden). Das verhindert, dass ein Angreifer, der über DCR eine eigenen eigenen OAuth-Client registriert hat, unbemerkt an das Token des Opfers gelangt.

  • Wiki.js-Ratenlimit: authentication.login ist pro IP auf 5 Aufrufe/min begrenzt, und alle Delegations-Logins kommen von der IP des MCP-Servers. Der Broker, cachen JWTs (standardmäßig 30 min) und wiederholt bei Erreichen des Limits, sodass das im normalen Betrieb unsichtbar ist; verzögertungen von bis zu einer Minute sind möglich.

  • Widerruf: Standard-OAuth /revoke (pro Token); eine Deaktivierung eines Benutzers in Wiki.js unterbricht die Delegation beim nächste JWT-Refresh (≤30 min); das Löschen der Datei SESSION_STORE_FILE + Neustart des MCP-Servers beendet alle Sessions auf der einmal.

  • Audit: Jeder Tool-Aufruf wird strukturiert protokolliert (wer, welches Tool, ok/denied) – ohne Seiteninhalt.

  • MCP-Endpunkt: bearer-only, 120 requests/min pro Token, Security-Header; die OAuth-Endpunkte werden durch die eingebaute Ratenbegrenzung des SDK geschützt.

Einschränkungen und Pläne

  • RAG/semantische Suche ist ein separater zukünftiger Dienst. Der Anschlusspunkt ist bereit: search_wiki funktioniert über die SearchBackend-Schnittstelle (src/search/ – v1 = native Wiki.js-Suche; der RAG-Dienst erhält das Wiki.js-JWT des Benutzers und bewahrt dadurch das ACL-Modell). Siehe docs/rag-integration.md.

  • Nur eine MCP-Serverinstanz (FileStore + In-Memory-Replay-Cache). HA erfordert einen gemeinsamen Store (Redis) – die KVStore-Schnittstelle ist bereits extrahiert.

  • Wiki.js 3.x verwendet unterschiedlichen Authentifizierungsmechanismus – das Modul zählt auf 2.5.x.

Lizenz

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