Skip to main content
Glama
README.md
# honest-calendar-mcp

Local Google Calendar MCP server. Your calendar data never leaves your machine except to Google. No third party in the middle.

Companion project to [honest-gmail-mcp](https://github.com/bartosz-kuc/honest-gmail-mcp).

## Why

Most Calendar integrations for AI assistants route your event data through a hosted service that sees everything: meetings, attendees, locations, private descriptions. This one doesn't.

**Data flow:** `You ↔ this server (on your Mac) ↔ Google Calendar API`. That's it.

**You can read the entire server** — one file, ~250 lines of Python — and confirm exactly what it can and cannot do.

## Features

Six tools exposed over MCP:

- `list_calendars` — all calendars available on this account
- `list_events` — events in a calendar within a time range, with optional free-text search
- `get_event` — full details of a single event
- `create_event` — new event (timed or all-day), with attendees, description, location, timezone, recurrence (RRULE), transparency (busy/free), and reminders
- `update_event` — partial patch of an existing event
- `delete_event` — delete an event

All tools that send invites accept a `send_updates` parameter (`none` by default — no email is sent unless you explicitly ask for it).

## Requirements

- Python 3.10+
- A Google account you want to give it access to
- A one-time setup in Google Cloud Console (~10 min, can reuse the OAuth client from honest-gmail-mcp if you already set that up)

## Setup

### 1. Clone + install

```bash
git clone https://github.com/bartosz-kuc/honest-calendar-mcp.git
cd honest-calendar-mcp
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
```

### 2. Get Google OAuth credentials

Same process as honest-gmail-mcp — a Desktop-app OAuth client from your own Google Cloud project. If you already have a project set up, just enable the Calendar API on it:

1. https://console.cloud.google.com/ (signed in with the account you want to authorize)
2. Select existing project (or create new one)
3. **APIs & Services → Library** → search **Google Calendar API** → **Enable**
4. Reuse existing OAuth consent screen / client, OR create new — Desktop app type
5. Save `credentials.json` in this repo's root directory

### 3. First run (does the OAuth dance)

```bash
./venv/bin/python server.py
```

Browser opens → sign in → **Allow**. Token saved locally as `token.json`. Press Ctrl+C after.

### 4. Register with your MCP client

**Claude Code:**

```bash
claude mcp add calendar-personal /absolute/path/to/venv/bin/python /absolute/path/to/server.py
```

**Claude Desktop:** edit `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "calendar-personal": {
      "command": "/absolute/path/to/venv/bin/python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}
```

### 5. Multiple accounts (optional)

Run one server instance per Google account, each with its own token file — no code changes. Three env vars override the defaults:

| Env var | Default | Purpose |
|---|---|---|
| `CALENDAR_TOKEN_PATH` | `token.json` | per-account token file |
| `CALENDAR_CREDENTIALS_PATH` | `credentials.json` | OAuth client (can be shared across accounts) |
| `CALENDAR_SERVER_NAME` | `calendar-personal` | MCP server name |

Authorize a second account (writes a separate token; sign in as that account in the browser):

```bash
CALENDAR_TOKEN_PATH="$PWD/token.work.json" ./venv/bin/python authorize.py
```

Then register a second instance pointing at that token, e.g. in `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "calendar-personal": {
      "command": "/absolute/path/to/venv/bin/python",
      "args": ["/absolute/path/to/server.py"]
    },
    "calendar-work": {
      "command": "/absolute/path/to/venv/bin/python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "CALENDAR_TOKEN_PATH": "/absolute/path/to/token.work.json",
        "CALENDAR_SERVER_NAME": "calendar-work"
      }
    }
  }
}
```

## Example usage

> "What's on my calendar tomorrow?"

AI calls `list_events` with tomorrow's time range → gets back events with summary, start, end, attendees.

> "Book a 1h call with alice@example.com next Thursday at 15:00."

AI calls `create_event` with summary, start, end, attendees, `send_updates: "all"` if you want Alice invited.

> "Add my Tuesday 19:30 kettlebells class every week, mark me free, no reminders."

AI calls `create_event` with `recurrence: ["RRULE:FREQ=WEEKLY"]`, `transparency: "transparent"`, and `reminders: {"useDefault": false}`.

## Data flow (detail)

```
Your AI client (Claude Code / Claude Desktop)
         ↕  MCP protocol over stdio (local process pipe)
This server (Python, on your machine)
         ↕  HTTPS to googleapis.com
Google Calendar API
```

No cloud middle. No telemetry. `credentials.json` and every `token*.json` stay on your disk and are `.gitignore`d.

## Security notes

- **You own the OAuth client.** Nobody else can revoke, rotate, or misuse it.
- **Revoke anytime** at https://myaccount.google.com/permissions.
- **Scope requested:** `calendar` (full read/write on all your calendars). Google does not offer read-only + write-only splits for the standard Calendar scope; the write-heavy nature of a calendar-editing tool needs full scope.
- **No secrets in git.** `.gitignore` blocks `credentials.json`, `token.json`, per-account `token.*.json`, and virtualenvs.
- **send_updates defaults to "none"** — the AI cannot accidentally spam attendees. You must explicitly ask for updates to be sent.

## Author

**Bartosz Kuć** — Warsaw-based developer, JDG owner running skanfirmy.pl.

- Site: https://skanfirmy.pl
- GitHub: https://github.com/bartosz-kuc

- Email: firma@bartosza.pl

## Consulting

Available for consulting on Polish tax and business integrations (KSeF, GUS/NFZ/GIOŚ APIs, mBank data), MCP server design, and AI-assisted tooling for JDGs and small teams. See **[skanfirmy.pl/uslugi](https://skanfirmy.pl/uslugi)** for productized packages (audit 3k PLN, setup 8-15k PLN, retainer 2-4k PLN/mo), or reach out via email.

## License

MIT — see [LICENSE](LICENSE).

TDQS

A3.5/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct resource and action: listing calendars vs. events, and get/create/update/delete for events. There is no overlap between any pair of tools, so an agent can select correctly without hesitation.

Naming Consistency5/5

All names follow a strict snake_case verb_noun pattern: list_calendars, list_events, get_event, create_event, update_event, delete_event. There are no deviations in style or verb forms.

Tool Count5/5

Six tools is well-scoped for a calendar server, covering the essential read/write/delete operations without bloat. Every tool has a clear place in the surface.

Completeness4/5

Event lifecycle is fully covered with list, get, create, update, and delete. Minor gaps exist such as no search/free-busy query and no calendar management beyond listing, but core calendar workflows are complete and workable.

Maintenance

ActivityMaintained
ResponsivenessNo issues