# Google Calendar Integration Design **Date:** 2025-01-02 **Status:** Approved **Primary Use Case:** Agenda overview ## Overview Build a `/gcal` slash command for Google Calendar access, following the same architectural pattern as `/gmail`: - OAuth credentials (reuse existing `~/.gmail-mcp/`) - Python API wrapper with tiered delegation - Skill file defining usage patterns - Read-only by default ## Architecture ``` User types /gcal │ ▼ Command (gcal.md) │ ├─→ invokes: skill:gcal │ ▼ Skill determines tier │ ├─→ Haiku: today, tomorrow, week, next (fetch + format) └─→ Sonnet: summary (fetch + analyze) │ ▼ Python helper (gcal_delegate.py) │ ├─→ Google Calendar API via OAuth └─→ Returns structured JSON │ ▼ PA formats response for user ``` ## Components | File | Format | Purpose | |------|--------|---------| | `~/.claude/commands/gcal.md` | Markdown | Slash command definition | | `~/.claude/skills/gcal/SKILL.md` | Markdown | Usage patterns and routing | | `~/.claude/mcp/delegation/gcal_delegate.py` | Python | API wrapper + delegation | | `~/.gmail-mcp/credentials.json` | JSON | OAuth credentials (add Calendar scope) | ## Command Interface ### Subcommands | Subcommand | Description | Tier | |------------|-------------|------| | `today` | Today's agenda | Haiku | | `tomorrow` | Tomorrow's agenda | Haiku | | `week` | Next 7 days, grouped by day | Haiku | | `next` | Next upcoming event | Haiku | | `summary` | Smart analysis of your week | Sonnet | ### Routing ``` /gcal → Smart default (today if before 6pm, tomorrow if after) /gcal today → Today's agenda /gcal tomorrow → Tomorrow's agenda /gcal week → Next 7 days, grouped by day /gcal next → Next upcoming event only /gcal summary → Sonnet-powered week analysis /gcal → PA interprets intent, routes to appropriate subcommand ``` ### Hybrid Approach 1. **Exact subcommand match first:** `today`, `tomorrow`, `week`, `next`, `summary` 2. **Natural language fallback:** - "what's on today" → today - "this week" → week - "next meeting" → next - "am I busy tomorrow" → tomorrow - "give me an overview" → summary 3. **Ambiguous input:** Ask for clarification ### Smart Default ```python from datetime import datetime def default_view(): return "today" if datetime.now().hour < 18 else "tomorrow" ``` ## Output Format ### Simple List (today/tomorrow/next) ``` 📅 Today — Thursday, Jan 2 9:00 AM Team standup (30m) 📍 Zoom · 👥 5 attendees 10:30 AM 1:1 with Sarah (45m) 📍 Conference Room B 2:00 PM Project review (1h) 📍 Google Meet · 👥 8 attendees 📝 Q4 roadmap discussion No more events today. ``` ### Grouped by Day (week) ``` 📅 This Week — Jan 2-8 ━━━ Thursday, Jan 2 ━━━ 9:00 AM Team standup (30m) 2:00 PM Project review (1h) ━━━ Friday, Jan 3 ━━━ 11:00 AM Client call (1h) ━━━ Monday, Jan 6 ━━━ (no events) ... ``` ### Context Fields - 📍 Location or meeting link - 👥 Attendee count - 📝 Description snippet (first ~50 chars) ### Smart Summary (Sonnet) > "Your week is front-loaded — Thursday and Friday are packed with 6 meetings totaling 5.5 hours. Monday-Wednesday are mostly clear, good for deep work. Heads up: the Client call Friday overlaps with your blocked focus time." ## Python Helper ### Structure ```python #!/usr/bin/env python3 """ Google Calendar Delegation Helper Usage: gcal_delegate.py today gcal_delegate.py tomorrow gcal_delegate.py week gcal_delegate.py next gcal_delegate.py summary """ SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'] CREDENTIALS_PATH = "~/.gmail-mcp/credentials.json" # Core functions def get_calendar_service() # OAuth flow, returns Calendar API client def fetch_events(start, end) # Returns list of event dicts def format_event(event) # Extracts: time, title, location, attendees, description def delegate(model, prompt) # Calls Claude CLI for Sonnet-tier tasks # Subcommand handlers def cmd_today() # fetch_events for today, format, return JSON def cmd_tomorrow() # fetch_events for tomorrow def cmd_week() # fetch_events for 7 days, group by date def cmd_next() # fetch next single event def cmd_summary() # fetch week, delegate to Sonnet for analysis ``` ### Output Format ```json { "tier": "haiku", "operation": "today", "date": "2025-01-02", "events": [...], "count": 3 } ``` ## OAuth Setup ### One-Time Setup 1. Go to [Google Cloud Console](https://console.cloud.google.com/) → APIs & Services 2. Enable "Google Calendar API" 3. OAuth consent screen → Add scope: `calendar.readonly` 4. Delete local token: `rm ~/.gmail-mcp/token.json` 5. Run `/gcal today` — triggers re-auth with new scope ### Scope Detection Helper detects missing scope and prompts: ``` Calendar scope not authorized. Run: rm ~/.gmail-mcp/token.json Then retry /gcal today to re-authenticate. ``` ## Delegation Tiers | Tier | Operations | Reason | |------|------------|--------| | Haiku | today, tomorrow, week, next | Fetch + format only | | Sonnet | summary | Requires analysis | | Opus | (reserved) | Strategic planning if needed | ## Policy - Read-only operations only - Show context (attendees, location) by default - Summarize results, don't dump raw data - Start with lowest capable model tier ## Implementation Checklist - [x] Add Calendar scope to GCP OAuth app - [x] Create `~/.claude/skills/gcal/SKILL.md` - [x] Create `~/.claude/commands/gcal.md` - [x] Create `~/.claude/mcp/delegation/gcal_delegate.py` - [x] Test OAuth re-authorization - [x] Test all subcommands - [ ] Test natural language fallback