Skip to main content
Glama
MaxPopov
by MaxPopov

wikijs-mcp-google-auth

기존 Wiki.js 2.5.x 위에 두는 MCP 계층: 기업 사용자가 Google Workspace로 로그인하고, LLM 클라이언트(claude.ai, Claude Desktop, 모든 MCP 클라이언트)를 통해 위키를 사용할 수 있습니다 — 자신의 Wiki.js 권한 범위 안에서만.

핵심 원칙: Wiki.js가 권한 판정의 단일 진실 원천(source of truth)입니다. MCP 서버에는 자체 사용자/그룹/권한이 없고 전역 API 키도 없습니다. 모든 작업은 개별 사용자의 네이티브 Wiki.js JWT로 수행되며, 허용/거부 결정(그룹 / 권한 / 페이지 규칙)은 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용 커스텀 인증 모듈 — MCP 서버가 서명한 RS256 애서션(assertion)을 검증하고 네이티브 Wiki.js JWT를 반환합니다 (상세)

packages/mcp-server/

원격 MCP 서버(Streamable HTTP): Google OIDC 기반 MCP 클라이언트용 OAuth 2.1 인가 서버 + 토큰 브로커 + 도구

packages/e2e-ui/

테스트 전용: 브라우저 UI e2e (Playwright) 및 독립 실행형 가짜 Google IdP 에뮬레이터

deploy/docker-compose.dev.yml

격리된 테스트 스탠드 (Wiki.js 2.5.303 + Postgres + ACL 초기 데이터) — 개발/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.company.com/mcp에 연결하고 OAuth 2.1(Dynamic Client Registration + PKCE)을 수행합니다. Google은 DCR을 지원하지 않으므로, MCP 서버가 클라이언트에게는 인가 서버 역할을 하고, Google은 인간 사용자를 인증하는 데에만 사용됩니다. Google 토큰은 서버를 벗어나지 않으며, 클라이언트는 MCP 서버 자체의 불투명(opaque) 토큰을 받습니다. Google 로그인 후 사용자에게는 애플리케이션 이름과 리다이렉트 URI가 표시되는 **동의 화면(consent screen)**이 나타납니다 — 혼동된 대리인(confused deputy) 방어를 위한 것입니다 (타사에 등록된 클라이언트가 사용자의 동의 없이 토큰을 얻을 수 없도록). 승인은 사용자별 · 클라이언트별로 기억됩니다.

  2. Google의 id_token이 검증됩니다(서명, iss, aud, email_verified, hd = 사용자의 Workspace 도메인).

  3. MCP 서버의 토큰 브로커가 Google 신원을 네이티브 Wiki.js JWT로 교환합니다. 짧은 수명의 RS256 애셜레이션(TTL 60초, 고유한 jti)에 서명하고, mcpdelegation 전략으로 표준 GraphQL mutation authentication.login을 호출합니다. Wiki.js 모듈이 애셜레이션을 검증하고, 이메일로 사용자를 확인한 뒤, 표준 refreshToken() 흐름을 통해 JWT를 반환합니다. JWT는 캐시되고 만료 전에 갱신됩니다.

  4. 모든 도구 호출은 Authorization: Bearer <사용자 JWT>와 함께 Wiki.js GraphQL로 전송됩니다. 권한이 없는 페이지는 읽거나 변경할 수 없고, 검색/목록에도 나타나지 않습니다 — e2e 테스트로 검증됩니다(서로 다른 그룹의 두 사용자에 대한 허용/차단 매트릭스).

도구

도구

설명

whoami

사용자 신원 + Wiki.js 그룹 및 권한 (접근 진단)

search_wiki

전문 검색; 결과는 사용자 권한에 따라 필터링됩니다

get_page

id 또는 경로로 페이지 조회 (메타데이터 + 전체 markdown)

list_pages

사용자에게 표시되는 페이지 (경로 접두어로 필터링)

create_page

페이지 생성 (markdown)

update_page

읽기-병합-쓰기; 지정되지 않은 필드는 유지됩니다

delete_page

삭제 (파괴적 작업; delete:pages 권한은 Wiki.js가 강제)


Wiki.js에 통합하기: 단계별 안내

필요 사항: Wiki.js 파일 시스템/Docker 설정에 접근할 수 있는 2.5.x (2.5.303에서 테스트됨); 공개 HTTPS 엔드포인트가 있는 MCP 서버 호스트; Workspace의 Google Cloud Console 관리자 권한.

1단계. Wiki.js에 인증 모듈 설치하기

Docker: 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이어야 합니다)

베어 메탈: 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)sir-assertion-key.pub.pem의 내용;

  • Expected Audience / Issuer — 기본값 유지 (urn:wikijs:mcp-delegation / urn:wikijs-mcp-google-auth);

  • User Lookup Provider Priority — 이메일로 사용자를 조회할 공급자 우선순위. 위키에 Google/OIDC로 로그인한다면 해당 공급자를 첫 번째로 둡니다 (모듈 키 google, oidc, local도 허용);

  • (선택) Self-registration + 도메인 화이트리스트 + 자동 그룹 등록 — 첫 MCP 요청 시 새 Workspace 사용자가 자동 생성되도록 설정;

  • 저장.

전략 인스턴스 키가 목록에 표시됩니다(이 키가 MCP 서버의 WIKIJS_STRATEGY_KEY입니다. UI에서 수동 생성 시 Wiki.js가 uuid를 생성하며, 이를 복사하십시오).

TFA(2단계 인증)가 활성화된 계정은 위임을 통해 사용할 수 없습니다. MCP 서버가 명확한 오류를 반환합니다.

4단계. Google OAuth 클라이언트 만들기

Google Cloud Console → APIs & Services → Credentials → Create credentials → OAuth client ID:

  • Application type: Web application;

  • Authorized redirect URI: https://mcp.company.com/oauth/google/callback (즉, PUBLIC_URL + /oauth/google/callback);

  • OAuth consent screen: type Internal (Workspace 내부 전용).

클라이언트 ID와 클라이언트 시크릿을 저장합니다.

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

태그된 이미지 (Release on main 워크플로우가 main에 version bump가 머지되면 자동으로 ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z를 게시합니다. 또는 로컬 빌드: docker build -f packages/mcp-server/Dockerfile -t wikijs-mcp-server:local .).

PUBLIC_URL

MCP 서버의 공개 HTTPS URL

WIKIJS_URL

Wiki.js URL (내부 망 주소를 권장)

WIKIJS_STRATEGY_KEY

3단계의 전략 인스턴스 키 (mcpdelegation으로 명명했다면 그 값)

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET

4단계에서 생성한 값

GOOGLE_ALLOWED_DOMAIN

예: company.com (사용자의 Workspace 도메인. 외부 도메인 계정은 거부)

포트 8000 앞에 TLS 리버스 프록시를 둡니다. 최소 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 → 같은 URL로 custom connector 추가 (또는 이전 버전은 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. 접근 가능한 페이지를 찾거나 열도록 요청 → 정상 동작.

  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-e2edev/main에 푸시될 때만 실행되므로(즉, 머지 전) PR 반복 속도를 늦추지 않습니다.

브라우저 UI e2e (Playwright) — 역할별

별도의 docker 스택 deploy/docker-compose.e2e.yml가짜 Google IdP 에뮬레이터(packages/e2e-ui/idp/ — 실제 Google 대신 역할 선택 화면이 있는 로그인 페이지)와 Wiki.js, MCP 서버, Playwright 러너를 띄웁니다. Playwright 러너는 서로 다른 역할(John/Kate/out-of-domain)로 브라우저 OAuth+동의 플로우를 전체 수행합니다. 에뮬레이터와 Playwright는 이 e2e 스택에서만 함께 동작하며, 프로덕션/개발 이미지에는 포함되지 않습니다.

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으로의 푸시에서 이 테스트를 수행합니다.

테스트 스탠드(stand)를 대상으로 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

Releases

릴리스는 자동으로 이루어집니다. dev에서 루트 package.jsonversion을 올리고, devmain PR을 연 뒤 병합하세요. 그러면 main으로의 푸시 시 Release on main 워크플로가 빌드하여 ghcr.io/<owner>/wikijs-mcp-server:vX.Y.Z(+ :latest)로 푸시하고, git 태그 vX.Y.Z와 GitHub Release을 생성합니다—모두 한 번의 실행으로 처리되며 내장된 GITHUB_TOKEN만 사용합니다(설정할 PAT/secret 없음). 버전이 변경되지 않으면 실행은 no-op이므로, main으로의 일반적인 병합은 릴 것을 만들지 않습니다.

이 기능이 동작하려면 일회성 저장소 설정이 필요합니다: Settings → Actions → General → Workflow permissions = Read and write permissions, 그리고 태그를 ruleset으로 보호한다면 v* 태그를 생성하도록 GitHub Actions를 허용하세요.

보안 참고 사항

  • Assertion: RS256, TTL 60초, 고유한 jti, 재생 방지 기능이 적용됩니다. 프라이빗 키는 MCP 서버에만 존재합니다. 키가 유출되면 어느 위키 사용자로든 로그인할 수 있으므로, 최상위 시크릿으로 취급하고 교체하세요(새 키 쌍 + 전략의 공개 키 업데이트).

  • Google identity: 정식 식별자는 iss+sub이며, 이메일은 조회 용도입니다. hd 도메인은 서명된 id_token에서 검증되며, 파라미터에서 가져오지 않습니다.

  • Confused-deputy 방어: 인가 코드가 발급되기 전에 사용자는 클라이언트별 동의 화면을 거칩니다(신뢰되는 퍼스트파티 시나 리오에서만 requireConsent로 비활성화 가능). 이는 DCR을 통해 자신의 OAuth 클라이언트를 등록한 공격자가 피해자의 토큰을 조용히 획득하는 것을 막습니다.

  • Wiki.js rate limit: authentication.login는 IP당 분당 5건이며, 모든 위임 로그인은 MCP 서버의 IP에서 발생합니다. 브로커는 JWT를 캐시(기본 30분)하고 한도에 걸리면 대기 후 재시도하므로, 정상 동작에서는 나타나지 않습니다. 대량 온보딩 중에는 최대 1분 정도의 지연이 발생할 수 있습니다.

  • Revocation: 표준 OAuth /revoke(토큰별); Wiki.js에서 사용자를 비활성화하면 다음 JWT 갱신(≤30분) 시 위임이 중단되고, SESSION_STORE_FILE을 삭제하고 MCP 서버를 재시작하면 모든 세션이 한 번에 해제됩니다.

  • Audit: 모든 도구 호출은 페이지 내용 없이 구조화된 형태(누가, 어떤 도구, ok/denied)로 기록됩니다.

  • MCP endpoint: bearer-only, 토큰당 120 requests/min, 보안 헤더; OAuth 엔드포인트는 SDK에 내장된 rate limiting으로 보호됩니다.

제한 사항 및 계획

  • RAG/의미론적 검색은 별도의 향후 서비스입니다. 연결 지점은 준비되어 있습니다. search_wikiSearchBackend 인터페이스(src/search/ — v1 = 네이티브 Wiki.js 검색; RAG 서비스는 사용자의 Wiki.js JWT를 받아 ACL 모델을 유지합니다)를 통해 동작합니다. docs/rag-integration.md를 참조하세요.

  • 단일 MCP 서버 인스턴스(FileStore + 인메모리 리플레이 캐시). HA를 위해서는 공유 저장소(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