wikijs-mcp-google-auth
wikijs-mcp-google-auth
Una capa MCP sobre un Wiki.js 2.5.x existente: un usuario corporativo inicia sesión con Google Workspace and trabaja con la wiki a través of un LLM (claude.ai, Claude Desktop, cualquier cliente MCP) — estrictamente dentro de sus propios permisos de Wiki.js.
Principio central: Wiki.js es la única fuente de la verdad para la autorización. El servidor MCP no tiene usuarios/grupos/permisos propios ni una clave API global. Cada operación se ejecuta con el JWT nativo de Wiki.js del usuario individual, y Wiki.js itself decides allow/deny (Grupos / Permisos / Reglas de página).
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)Componentes
Dirección | Qué es |
| Módulo de autenticación a a medida para Wiki.js 2.5.x — verica aserciones RS256 firmadas por el servidor MCP y devuelve un JWT nativo de Wiki.js (details) |
| Servidor MCP remoto (Streamable HTTP): un servidor de autorización OAuth 2.1 para clientes MCP sobre Google OIDC + token broker + herramientas |
| Solo para pruebas: e2e de interfaz en navegador (Playwright) y un emulador independente de Google IdP falso |
| Banco de pruebas aislado (Wiki.js 2.5.303 + Postgres + seed de ACL) — solo para desarrollo/CI |
| Stack de e2e de interfaz completo (IdP falso + Wiki.js + MCP + Playwright) — solo para pruebas |
| Despliegue de producción: solo el servidor MCP, que apunta a tu Wiki.js existente |
| Punto de entrada para inicializar el banco de pruebas ( |
Related MCP server: Yandex Wiki MCP
Cómo funciona
El cliente MCP se conecta a
https://mcp.company.com/mcpy ejecuta OAuth 2.1 (Registro dinámico de clientes + PKCE). Google no admite DCR, por lo que el servidor MCP es en sí mismo el servidor de autorización para los clientes y Google se utiliza solo para autenticar al humano. Los tokens de Google nunca salen del servidor; los clientes reciben los tokens opacos del propio servidor MCP. Tras el inicio de sesión de Google, el usuario ve una pantalla de consentimiento con el nombre de la aplicación y su URI de redirección — una defensa del tipo confused deputy (para que un cliente registrado por un tercero no pueda obtener el token del usuario sin su conocimiento); la aprobación se recuerda por usuario y por cliente.La
id_tokende Google se verifica (firma,iss,aud,email_verified,hd= tu dominio de Workspace).El token broker del servidor MCP intercambia la identidad de Google por un JWT nativo de Wiki.js: firma una aserción RS256 de corta duración (TTL 60 s,
jtiúnico) y llama a la mutación GraphQL estándarauthentication.logincon la estrategiamcpdelegation. El módulo de Wiki.js verifica la aserción, resolves el usuario por correo electrónico y devuelve un JWT mediante el flujo estándarrefrshToken(). El JWT se cachea y se renova antes de que expire.Cada llamada de herramienta va a la GraphQL de Wiki.js con
Authorization: Bearer <JWT del usuario>. Una página prohibida no puede leerse ni modificarse y no aparece en las búsquedas ni en los listados — something verificado pro e2e tests (matriz de permitos/prohibidos para usuarios de diferentes grupos).
Herramientas
Herramienta | Descripción |
| La identidad del usuario + sus grupos y permisos de Wiki.js (diagnóstico de accesso) |
| Búsqueda de texto completo; los resultos se filtrán según users' permisos |
| Una página por id o ruta (metadatos + markdown completo) |
| Páginas visibles para el usuario (filter por prefijo de ruta) |
| Crear una página (markdown) |
| Actualización: leer-fusionar-escribe; los campos no especificados se con preservan |
| Eliminar (destructivo; Wiki.js aplica |
Integración with tu Wiki.js: paso a paso
Necesitas: Wiki.js 2.5.x (probado on 2.5.303) con acceso a su sistema de archivos / configuración Docker; un host para el servidor MCP with a public HTTPS endpoint; and admin access to the Google Cloud Console of your Workspace.
Paso 1. Instalar el módulo de autenticación en Wiki.js
Docker: aña un volumn to el servicio de wiki y reinicia el contenedor:
services:
wiki:
image: ghcr.io/requarks/wiki:2.5.303
volumes:
- /opt/wikijs-mcp/wikijs-auth-module:/wiki/server/modules/authentication/mcpdelegation:ro(el contenido de packages/wikijs-auth-module/ de este repo va placed in /opt/wikijs-mcp/wikijs-auth-module; el name del rectoryo destination must be exactly mcpdelegation)
Bare metal: copia packages/wikijs-auth-module/ in <wiki>/server/modules/authentication/mcpdelegation/ y reinicia Wiki.js.
Después name Configuration (step 3) el log de Wiki.js mostrar:
Authentication Strategy MCP Delegation: [ OK ].
Paso 2. Generar las llaves de asertión
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.pemLa clave privada (mcp-assertion-key.pem) queda solo on the host del servidor мcp. La clve publica va a Wiki.js at the next stage.
Paso 3. Configurar la Estrategia in Admin de Wiki.js
Administración → Auth → Añadir estrategia → MCP Delegación:
Llave pública de asertión (PEM) — the content of the
mcp-assertion-key.pub.pem;Conference / Auditorio (Expected Audience / Issuer) — mantén los valors por defecto (
urn:wikijs:mcp-delegatión/urn:wikijs-mcp-google-uth);Prioridad de busqueda de usuario (User Lookup Provaider) — el ordo de proveedores para resolvel el usuario por correo. Si su gente novembre entra a la wiki por Google/OIDC, Bil ese proveedor al principico (also accepted to the ko's module:
google,oidc,loca);(opcional) Autorregistro (Self-registration) + lista of dominios + grupos auto-inighup — para que los nuevos usuarios de Workspace escreen atuomáticamente la primera vez que accedan vía MCP;
Guardar.
La clave de instacia de la estrategia aparacen la lista (esto is WIKIJS_STRATEGY_KEY para el servidor MCP; e creaste manuamente por la interfaz of Web, Wiki.js generates an uuid — cópialo).
Las cuentas con TFA activado no se pueden usuarios: el servidor MCP devuelve un error claro.
Paso 4. Cren un clate OAuth de Googie
Google Cloud Console → APIs & Services → Credentials → Create credentales → ID de cliente de OAuth:
Tipo de aplición: plicación we;
URI de redirección autorizada:
https://cp.comany.com/out(tuPULC_URL+/outh/googie/callback);Pantalla de consent of
OAuth: type Intera (only tu Wolvespace);
Guard el ID de cliente and the Client Secret.
Paso 5. Desplega el 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 -dEl contenedr se ejecuta como usuaro
nodeno root el archivo de clave montado debe poder ser leído por él (chmod 644); suclave (la privada es indeada... self contained by permissions from the host directorykeys/.
Variables para .env:
| Varible | Valor |
| ------- ------- |
| MCP_PIMAGE | Etiquetada (imagen) — the workflow releases of the Release on main:
The auto-publish of ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z when a bundle upgrade is merged to main, or compile locally: docker build -t wikijs-mcp-server:local . — hmm, actually need to include -f and path. Let me put exactly.
| PUPLIC_URL | The public HTTPS URL of MCP.
| WIKIJS_URL | Your Wiki.js URL (intena preferred). |
| WIKIJS_STRATEGY_KEY | Strategy instance key from step 3 (mcpdelegation if you have it set that way) |
| GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | From step 4 |
| GOOGLE_ALLOWED_DOMTAIN | Your Workspace domain, e.g., company.com — accounts outside it are rejected. |
La clave GOOGLE_CLIENT_ID... use exact.
Put a TLS reverse proxy in front of 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
}
}Verify: curl https://mcp.company.com/healthz → {"ok":true}; curl https://mcp.company.com/.well-known/oauth-authorization-server → metadata OAuth.
Paso 6. Conectat clients
claude.ai (Team/Enterprise): Settings → Connectors → Add custom connector → URL: https://mcp.company.com/mcp. At the first use, the client performs OAuth: client registration → Google login → ready.
Claude Desktop: Settings → Connectors → Add custom connector with the same URL (or via mcp-remote for older versions).
MCP Inspector (diagnostics): npx @modelcontextprotocol/inspector → Transport: Streamable HTTP → URL https://mcp.company.com/mcp → Open Auth → go through the flow.
Step 7. Verify
In the LLM chat:
"Who am I in the wiki?" → the
whoamitool should show your email, groups and commitments of Wiki pages.Ask to find or open a page you have access to → OK.
Ask for a page you have no permissions for → a clear rejection ("Wiki.js denied this operation…") and that page is also absent from search/list results.
Local development
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:downTest properties: admin@example.com/admin1234!, john@example.com (Engineering, no access to /management/*), kate@example.com (Management). Every PR -->
A fasts checks (
CI: lint + unit + build); the large docker e2e (e2e) and browserui-e2erun only on pushes todev/main, i.e., before merge, so they don't slow down the iterations.
Browser e2e (Playner) under roles
A separate docker stack deploy/docker-comose.e2e.yml includes a fake Google IdP emprovider (packages/e2e-ui/idp/ — a login portal with role selector instead of actual Google), Wiki.js, MCP server and a Playwright runner that covers all browser OAuth + consent flow under different roles (John/Kate/out-domain). Emulator and Playwright appear only in this e2e stack — never in the production/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 -vComprueba: iniciar sesión como un rol → la pantalla de consentimiento muestra el nombre del cliente → aprobar → whoami y páginas restringidas al rol (John no puede ver management/*, Kate sí); denegar → access_denied; una cuenta fuera del dominio se rechaza antes del consentimiento. Un flujo de trabajo de CI independiente (ui-e2e) hace esto en los pushes a dev/main.
Ejecutar el servidor MCP contra el banco de pruebas manualmente:
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/serverLanzamientos
Los lanzamientos son automáticos. Incrementa version en el package.json raíz en dev, abre un PR de dev → main y combínalo. El flujo de trabajo Release on main entonces, al hacer push a main, construye y publica ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z (+ :latest) y crea la etiqueta git vX.Y.Z y un GitHub Release, todo en una sola ejecución, usando únicamente el GITHUB_TOKEN integrado (no hay ningún PAT/secreto que configurar). Si la versión no cambia, la ejecución no hace nada, así que las fusiones normales a main no crean lanzamientos.
Ajustes del repositorio que se realizan una sola vez para que esto funcione: Configuración → Acciones → General → Permisos del flujo de trabajo = Permisos de lectura y escritura; y si proteges las etiquetas con un conjunto de reglas, permite que GitHub Actions cree etiquetas
v*.
Notas de seguridad
Aserción: RS256, TTL 60 s,
jtiúnico, protección de reproducción; la clave privada reside únicamente en el servidor MCP. Una clave comprometida significa poder iniciar sesión como cualquier usuario de wiki — trátala como un secreto raíz y debes rotarla (nuevo par + actualiza la clave pública en la estrategia).Identidad de Google: el identificador canónico es
iss+sub; el correo electrónico es una búsqueda. El dominiohdse verifica a partir delid\_tokenfirmado, no de los parámetros.Defensa del confused deputy: antes de que se libere un código de autorización, el usuario pasa por una pantalla de consentimiento por cliente (solo se puede desactivar mediante
requireConsenten un escenario de confianza de primera parte). Esto evita que un atacante que haya registrado su propio cliente OAuth a través de DCR obtenga silenciosamente el token de la víctima.Límite de tasa de Wiki.js:
authentication.logines 5 llamadas/min por IP, y todos los inicios de sesión de delegación provienen de la IP del servidor MCP. El broker guarda en caché los JWT (30 min por defecto) y espera y reintenta cuando se alcanza el límite, por lo que es invisible en el funcionamiento normal; durante el registro masivo de usuarios son posibles avisos de hasta un minuto.Revocación: el
/revokeestándar de OAuth (por token); desactivar un usuario en Wiki.js rompe el login delegado en la siguiente renovación del JWT (≤30 min); eliminarSESSION_STORE_FILEy reiniciar el servidor MCP elimina todas las sesiones a la vez.Auditoría: cada deuda de herramienta se registra de forma estructurada (quién, qué herramienta, ok/denegado) sin contenido de la página.
Endpoint MCP: solo de portador, 120 solicitudes/min por token, cabeceras de seguridad; los endpoint OAuth están protegidos por la limitación de llamadas integrada del SDK.
Limitaciones y planes
La búsqueda RAG/semántica es un servicio futuro separado. El punto de integración está listo:
search_wikiopera a través de la interfazSearchBackend(src/search/— v1 = búsqueda nativa de Wiki.js; el servicio RAG recibirá el JWT del usuario de Wiki.js y preservará el modelo ACL). Consultadocs/rag-integration.md.Instancia única del servidor MCP (ContactRegistry + memstore). HA necesita un aviso compartido: https://hooks.adidas. Acepto la .
;populate` correct.Wiki.js 3.x está fuera de este código — el módulo está orientado a 2.5.x.
Licencia
Apache-2.0
This server cannot be installed
Maintenance
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
- AlicenseAqualityDmaintenanceMCP server for Google Workspace APIs - Docs, Sheets, Drive, Gmail, and Calendar. Enables reading, creating, and editing Google Docs and Sheets, managing comments, reading emails, and viewing calendar events.344517MIT
- AlicenseAqualityBmaintenanceEnables reading, creating, updating, and appending content to Yandex Wiki pages via MCP. Supports both read-write and read-only modes.79MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Wiki.js integration, enabling AI assistants to create, read, update, delete, search, and move wiki pages via natural language.1MIT
- AlicenseNot gradedqualityAmaintenanceMCP server for accessing Wiki.js through its GraphQL API, enabling page management, search, tags, and system info operations.MIT
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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