Skip to main content
Glama
README.md
# gcal-mcp

An MCP server for Google Calendar and Google Tasks, designed for use with Claude Code. Paste a flight confirmation, manage tasks with energy-aware scheduling, queue articles for reading — all through natural language.

## What It Does

- **Flight events** — Paste a confirmation email, get a timezone-aware calendar event (`SFO → JFK | AA 1234`)
- **Lodging events** — Paste a booking confirmation, get 3 events: all-day stay span, timed check-in, timed check-out
- **Reading queue** — Save articles to read later, batch-schedule them into configurable morning reading slots
- **Task manager** — Create tasks with Eisenhower priority quadrants and energy levels, synced to Google Tasks
- **Energy-aware scheduling** — Define your daily energy profile; high-energy tasks get scheduled into your peak hours
- **Daily planning** — Get optimized schedule proposals, rearrange task blocks, set tickler reminders

## Setup

### 1. Google Cloud Project

1. Go to [Google Cloud Console](https://console.cloud.google.com/) and create a new project
2. Enable the **Google Calendar API** and **Google Tasks API** (APIs & Services > Library)
3. Configure the **OAuth consent screen**:
   - User type: External
   - Add scopes: `https://www.googleapis.com/auth/calendar` and `https://www.googleapis.com/auth/tasks`
   - Add your Google email as a test user
   - Publishing status: leave as "Testing"
4. Create **OAuth credentials**:
   - Credentials > Create Credentials > OAuth client ID
   - Application type: **Desktop app**
   - Download the JSON file and save it as `credentials.json` in the project root

### 2. Install & Build

```bash
git clone <this-repo>
cd gcal-mcp
npm install
npm run build
```

### 3. Authenticate

Run the one-time OAuth setup (this opens your browser):

```bash
npm run auth
```

You'll be redirected to Google to grant calendar and tasks access. After approving, the token is saved locally in `data/token.json`.

> **Note:** If you're in Google's "Testing" mode, the refresh token expires after 7 days of inactivity. Just run `npm run auth` again if that happens.

### 4. Register with Claude Code

Add to your `~/.claude/.mcp.json` (global) or project-level `.mcp.json`:

```json
{
  "mcpServers": {
    "gcal": {
      "command": "node",
      "args": ["/absolute/path/to/gcal-mcp/dist/index.js"]
    }
  }
}
```

Restart Claude Code. All tools should now be available.

## Tools

### Calendar

| Tool | Description |
|---|---|
| `create_flight_event` | Create a flight event from extracted confirmation details |
| `create_lodging_event` | Create 3 lodging events (stay span, check-in, check-out) |
| `list_events` | List all events for a given date |

### Reading Queue

| Tool | Description |
|---|---|
| `queue_reading` | Save an article URL to the reading queue |
| `list_reading_queue` | Show all queued articles |
| `remove_reading` | Remove an article from the queue |
| `schedule_readings` | Batch-schedule queued articles into reading time slots |

### Task Manager

| Tool | Description |
|---|---|
| `add_task` | Create a task with priority quadrant, energy level, and duration |
| `quick_add_task` | Create a task and schedule it in one call |
| `list_tasks` | List tasks with optional filters (quadrant, energy, status) |
| `update_task` | Update task fields |
| `complete_task` | Mark a task as done |
| `schedule_task` | Schedule a task into a free calendar slot |
| `create_tickler` | Set a reminder to revisit a task on a future date |

### Scheduling

| Tool | Description |
|---|---|
| `suggest_schedule` | Propose an optimized daily schedule based on priorities and energy |
| `rearrange_schedule` | Clear and re-propose task blocks for a day |
| `set_energy_profile` | Define your daily energy windows (peak hours, low-energy times) |

## Usage

Just tell Claude what you want in natural language:

**Flights:**
> "Here's my flight confirmation: [paste email text]"

**Lodging:**
> "Here's my Airbnb booking: [paste email text]"

**Tasks:**
> "Add a task to review the Q3 report, it's urgent and important, high energy, about 45 minutes"

**Scheduling:**
> "Suggest a schedule for tomorrow"
> "Schedule my pending tasks for today"

**Reading:**
> "Save this article for later: https://example.com/article"
> "Schedule my reading queue"

## Customization

### Config file

Copy `config.default.json` to `config.json` to override settings:

```bash
cp config.default.json config.json
```

`config.json` is gitignored, so your personal settings won't be committed. Available options:

| Key | Default | Description |
|---|---|---|
| `readingWindows` | 5:30 AM and 10:00 AM, 30 min each | Time slots for scheduled reading events |

### Energy profile

Set your energy profile through the `set_energy_profile` tool. The default profile is:

| Time | Energy Level |
|---|---|
| 9:00 – 11:00 AM | High |
| 11:00 AM – 1:00 PM | Medium |
| 1:00 – 3:00 PM | Low |
| 3:00 – 5:00 PM | Medium |
| 5:00 – 6:00 PM | Low |

Your profile is saved in `data/profile.json` and persists across sessions.

### Templates

Each template file has customizable constants at the top:

| File | What to customize |
|---|---|
| `src/templates/flight.ts` | Title format, color (default: Blueberry/blue) |
| `src/templates/lodging.ts` | Title format, color (default: Sage/green), check-in/out block duration |
| `src/templates/reading.ts` | Title format, color (default: Lavender/purple) |
| `src/templates/task.ts` | Title format, color (default: Banana/yellow) |

After modifying templates, rebuild with `npm run build`.

## Project Structure

```
├── config.default.json       # Default settings (tracked)
├── config.json               # Your local overrides (gitignored)
├── credentials.json          # OAuth client credentials (gitignored, you provide)
├── data/                     # Runtime data (gitignored)
│   ├── token.json            # OAuth refresh token
│   ├── reading-queue.json    # Reading queue
│   ├── tasks-meta.json       # Task metadata (quadrant, energy, scheduling)
│   └── profile.json          # Energy profile
src/
├── index.ts                  # MCP server entry point, tool registration
├── config.ts                 # Config loader (defaults + local overrides)
├── auth.ts                   # OAuth2 flow + token management
├── auth-cli.ts               # Standalone auth script for first-time setup
├── calendar.ts               # Google Calendar API wrapper
├── reading-queue.ts          # Reading queue persistence
├── tasks.ts                  # Google Tasks API wrapper
├── tasks-meta.ts             # Local task metadata (quadrant, energy, scheduling)
└── templates/
    ├── flight.ts             # Flight event formatting
    ├── lodging.ts            # Lodging event formatting
    ├── reading.ts            # Reading event formatting
    └── task.ts               # Task time block formatting
```

## Google Calendar Event Colors

| colorId | Name | Used for |
|---|---|---|
| `"9"` | Blueberry (blue) | Flights |
| `"2"` | Sage (green) | Lodging |
| `"1"` | Lavender (purple) | Reading |
| `"5"` | Banana (yellow) | Task blocks |
| `"3"` | Grape (purple) | Tickler reminders |

Available colors: Lavender (1), Sage (2), Grape (3), Flamingo (4), Banana (5), Tangerine (6), Peacock (7), Graphite (8), Blueberry (9), Basil (10), Tomato (11).

## License

MIT — see [LICENSE](LICENSE).