Skip to main content
Glama
REVREBEL

Google Calendar MCP OAuth Proxy

by REVREBEL

Google Calendar MCP OAuth Proxy

이 Worker는 Codex 같은 MCP 클라이언트와 Google의 공식 Calendar MCP 사이에서 OAuth 경계 역할을 합니다.

Codex / MCP client
        |
        | OAuth to this Worker
        v
Cloudflare OAuth Provider
        |
        | Google OAuth (client ID + client secret)
        v
Google OAuth
        |
        | Google access token
        v
Google Calendar MCP
https://calendarmcp.googleapis.com/mcp/v1

클라이언트는 Google OAuth 클라이언트 시크릿을 절대 받지 않습니다. Google 액세스 토큰과 리프레시 토큰은 Cloudflare OAuth 공급자가 관리하는 암호화된 OAuth grant 속성에 저장됩니다. 보호된 /mcp 핸들러는 MCP 트래픽을 업스트림으로 전달하기 전에 클라이언트의 로컬 베어러 토큰을 사용자의 Google 액세스 토큰으로 교체합니다.

Google scope

wrangler.jsonc는 GOOGLE_OAUTH_SCOPES의 Google Calendar scope를 정의합니다:

https://www.googleapis.com/auth/calendar.calendarlist.readonly
https://www.googleapis.com/auth/calendar.events.freebusy
https://www.googleapis.com/auth/calendar.events.readonly
https://www.googleapis.com/auth/calendar.calendars

Worker는 인증된 사용자를 식별하기 위해 콜백이 Google의 user-info 엔드포인트를 사용하므로 email profile을 자동으로 추가합니다.

Google 승인 요청 또한 access_type=offline 및 prompt=consent를 사용하므로 Google은 리프레시 토큰을 반환합니다.

Related MCP server: google-mcp-server

로컬 시크릿

예제 파일을 복사하세요:

cp .dev.vars.example .dev.vars

설정하세요:

GOOGLE_CLIENT_ID=<Google OAuth web client ID>
GOOGLE_CLIENT_SECRET=<Google OAuth client secret>
COOKIE_ENCRYPTION_KEY=<strong random secret>
HOSTED_DOMAIN=<optional Google Workspace domain restriction>

GOOGLE_OAUTH_SCOPES와 GOOGLE_MCP_URL은 wrangler.jsonc의 시크릿이 아닌 Worker 변수입니다.

Google Cloud OAuth 클라이언트

Google OAuth 웹 애플리케이션 클라이언트를 사용하세요.

승인된 리디렉션 URI는 이 Worker 또는 터널의 공개 호스트 이름에 /callback을 더한 값이어야 합니다:

https://mcp-auth.example.com/callback

위에 나열된 Calendar scope를 Google Auth Platform의 동의/데이터 액세스 구성에 추가하세요.

로컬 실행

의존성을 설치하고 Worker 타입을 생성하세요:

npm install
npm run cf-typegen

포트 5555에서 로컬로 Wrangler를 시작하세요:

npm run dev

로컬 엔드포인트는:

http://localhost:5555/mcp

OAuth는 공개 HTTPS 콜백을 요구하므로 엔드 투 엔드 로컬 테스트에는 Cloudflare Tunnel을 사용하세요.

고정된 명명된 터널

같은 콜백을 Google Cloud에 등록해야 하므로 안정적인 호스트 이름이 좋습니다.

npx wrangler dev --tunnel-name=mcp-google-auth --tunnel

명명된 터널 호스트 이름을 Wrangler 개발 서버로 라우팅하도록 구성하세요. 예를 들어:

https://mcp-auth.example.com  ->  local Wrangler dev server

그리고 등록하세요:

https://mcp-auth.example.com/callback

로 Google OAuth 리디렉션 URI로 사용합니다.

Codex에 노출되는 MCP URL은 다음과 같습니다:

https://mcp-auth.example.com/mcp

Codex 구성

이 Worker는 Codex가 보는 OAuth 인증 서버이므로 Codex에는 Google 클라이언트 ID나 Google 클라이언트 시크릿이 필요하지 않습니다.

[mcp_servers.google_calendar_proxy]
enabled = true
url = "https://mcp-auth.example.com/mcp"
auth = "oauth"

그런 다음 인증하세요:

codex mcp login google_calendar_proxy

예상되는 흐름은 다음과 같습니다:

  1. Codex가 이 Worker의 OAuth 엔드포인트를 발견합니다.

  2. Codex가 이 Worker에 등록/인증합니다.

  3. Worker가 브라우저를 Google로 보냅니다.

  4. Google이 Worker/터널의 /callback으로 돌아옵니다.

  5. Worker는 GOOGLE_CLIENT_SECRET을 사용하여 Google의 승인 코드를 교환합니다.

  6. Codex는 Worker가 발급한 OAuth 토큰을 받습니다.

  7. /mcp에 대한 호출은 사용자의 Google 액세스 토큰을 사용하여 Google 공식 Calendar MCP로 전달됩니다.

토큰 갱신 동작

Google 리프레시 토큰은 암호화된 OAuth grant에 보관됩니다. 프록시는 제한된 크기의 isolate-local LRU 캐시를 유지하며, 액세스 토큰 항목은 리프레시 시점에 도달하면 제거하고 캐시를 100명으로 제한합니다. 저장된 액세스 토큰이 만료되었거나 Google MCP가 401을 반환하면, Worker는 Google 리프레시 토큰과 Worker 쪽 클라이언트 시크릿을 사용해 새 Google 액세스 토큰을 발급하고 한 번 더 시도합니다.

인메모리 캐시는 최적화에 불과합니다. 새 Worker isolate는 항상 암호화된 grant 속성에서 새로 고칠 수 있습니다.

레거시 grant

리프레시 토큰 지원 이전에 생성된 OAuth grant에는 원본 Google 액세스 토큰과 사용자 메타데이터만 포함되어 있습니다. 프록시는 해당 grant를 감지하고 Google이 기존 액세스 토큰을 계속 허용하는 한 계속 사용합니다. Google이 해당 토큰을 거부하면 Worker는 401 invalid_token을 반환하여, 누락된 자격 증명으로 리프레시를 시도하는 대신 MCP 연결을 다시 인증할 수 있게 합니다.

Related MCP Connectors

Related MCP Servers