A Model Context Protocol (MCP) server for Google Calendar integration, with OAuth2/PKCE authentication and secure keychain storage.
- @solo-ist/auth — OAuth2 with PKCE, OS keychain storage, multi-account support
- @solo-ist/calendar-mcp — MCP server with Google Calendar tools
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable the Google Calendar API
- Create OAuth 2.0 credentials (Desktop application type)
- Add
http://127.0.0.1:3000as an authorized redirect URI - Copy the Client ID and Client Secret
Pull the pre-built image and add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"calendar": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-p", "3000:3000",
"-v", "calendar-mcp-data:/home/app/.gcp",
"-e", "GOOGLE_CLIENT_ID",
"-e", "GOOGLE_CLIENT_SECRET",
"ghcr.io/solo-ist/calendar-mcp"
],
"env": {
"GOOGLE_CLIENT_ID": "your-client-id",
"GOOGLE_CLIENT_SECRET": "your-client-secret"
}
}
}
}-ienables stdio for MCP communication-p 3000:3000exposes the OAuth callback port (needed during authentication)-v calendar-mcp-data:/home/app/.gcppersists tokens across container restarts- Environment variables are passed through from Claude Desktop
export GOOGLE_CLIENT_ID='your-client-id'
export GOOGLE_CLIENT_SECRET='your-client-secret'
./bin/setup.shThen add to Claude Desktop config:
{
"mcpServers": {
"calendar": {
"command": "node",
"args": ["/path/to/gcp/packages/calendar-mcp/dist/index.js"],
"env": {
"GOOGLE_CLIENT_ID": "your-client-id",
"GOOGLE_CLIENT_SECRET": "your-client-secret"
}
}
}
}Use the auth_add_account tool to start the OAuth flow, then complete it with auth_complete.
| Tool | Description |
|---|---|
list_events |
List calendar events in a date range |
get_event |
Get detailed event information by ID |
create_event |
Create a new calendar event |
delete_event |
Delete an event by ID |
find_free_time |
Query free/busy for calendars |
| Tool | Description |
|---|---|
auth_add_account |
Start OAuth flow to add a Google account |
auth_complete |
Complete OAuth with authorization code |
auth_list_accounts |
List all authenticated accounts |
auth_remove_account |
Remove an account |
| Variable | Description |
|---|---|
GOOGLE_CLIENT_ID |
OAuth client ID (required) |
GOOGLE_CLIENT_SECRET |
OAuth client secret (required) |
ENABLED_TOOLS |
Comma-separated list of enabled tools (default: read-only) |
GCP_PLAINTEXT_STORAGE |
Use plaintext storage instead of keychain (for CI/Docker) |
By default, only read-only tools are enabled. The server requests minimal scopes based on enabled tools:
- Read-only mode:
calendar.events.readonly+calendar.freebusy - Read-write mode:
calendar.events+calendar.freebusy
- Refresh tokens stored in OS keychain (macOS
security, Linuxsecret-tool) - Access tokens refreshed 5 minutes before expiry
- Plaintext fallback for CI/Docker (enable with
GCP_PLAINTEXT_STORAGE=true) - No tokens in logs
docker pull ghcr.io/solo-ist/calendar-mcpdocker build -t calendar-mcp .
docker run -i --rm \
-p 3000:3000 \
-v calendar-mcp-data:/home/app/.gcp \
-e GOOGLE_CLIENT_ID='your-client-id' \
-e GOOGLE_CLIENT_SECRET='your-client-secret' \
calendar-mcppnpm install
pnpm build
pnpm test
pnpm audit