Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions google-calendar/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Google Calendar MCP - Environment Variables
# Copy this file to .env and fill in your credentials

# Google OAuth 2.0 Credentials
# Get these from Google Cloud Console: https://console.cloud.google.com/
# 1. Create a project or select existing
# 2. Enable Google Calendar API
# 3. Create OAuth 2.0 credentials (Web application type)
# 4. Add authorized redirect URIs for your deployment

GOOGLE_CLIENT_ID=your_client_id_here
GOOGLE_CLIENT_SECRET=your_client_secret_here
4 changes: 4 additions & 0 deletions google-calendar/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
.env

219 changes: 219 additions & 0 deletions google-calendar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
# Google Calendar MCP

MCP Server for Google Calendar integration. Manage calendars, events and check availability using the Google Calendar API.

## Features

### Calendar Management
- **list_calendars** - List all user's calendars
- **get_calendar** - Get details of a specific calendar
- **create_calendar** - Create a new secondary calendar
- **delete_calendar** - Delete a calendar

### Event Management
- **list_events** - List events with date filters and search
- **get_event** - Get details of an event
- **create_event** - Create event with attendees and reminders
- **update_event** - Update existing event
- **delete_event** - Delete event
- **quick_add_event** - Create event using natural language

### Availability
- **get_freebusy** - Check busy/free time slots

### Advanced Operations
- **move_event** - Move an event between calendars
- **find_available_slots** - Find free time slots across multiple calendars
- **duplicate_event** - Create a copy of an existing event

## Setup

### 1. Create Project in Google Cloud Console

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Enable **Google Calendar API**:
- Sidebar → APIs & Services → Library
- Search for "Google Calendar API" and enable it

### 2. Configure OAuth 2.0

1. Go to "APIs & Services" → "Credentials"
2. Click "Create credentials" → "OAuth client ID"
3. Select "Web application"
4. Configure:
- Name: Google Calendar MCP
- Authorized JavaScript origins: your URL
- Authorized redirect URIs: your callback URL

### 3. Configure Environment Variables

Create a `.env` file with:

```bash
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
```

## Development

```bash
# Install dependencies (from monorepo root)
bun install

# Run in development (hot reload)
bun run dev

# Type check
bun run check

# Build for production
bun run build
```

## Usage Examples

### List events for next week

```json
{
"tool": "list_events",
"input": {
"timeMin": "2024-01-15T00:00:00Z",
"timeMax": "2024-01-22T00:00:00Z",
"singleEvents": true,
"orderBy": "startTime"
}
}
```

### Create event with attendees

```json
{
"tool": "create_event",
"input": {
"summary": "Planning Meeting",
"description": "Q1 roadmap discussion",
"location": "Conference Room",
"start": {
"dateTime": "2024-01-15T14:00:00-03:00",
"timeZone": "America/Sao_Paulo"
},
"end": {
"dateTime": "2024-01-15T15:00:00-03:00",
"timeZone": "America/Sao_Paulo"
},
"attendees": [
{ "email": "[email protected]" },
{ "email": "[email protected]" }
],
"sendUpdates": "all"
}
}
```

### Quick add event with natural language

```json
{
"tool": "quick_add_event",
"input": {
"text": "Lunch with client tomorrow at 12pm at Central Restaurant"
}
}
```

### Check availability

```json
{
"tool": "get_freebusy",
"input": {
"timeMin": "2024-01-15T08:00:00-03:00",
"timeMax": "2024-01-15T18:00:00-03:00",
"calendarIds": ["primary", "[email protected]"]
}
}
```

### Find available meeting slots

```json
{
"tool": "find_available_slots",
"input": {
"calendarIds": ["primary", "[email protected]"],
"timeMin": "2024-01-15T09:00:00-03:00",
"timeMax": "2024-01-15T18:00:00-03:00",
"slotDurationMinutes": 30,
"maxSlots": 5
}
}
```

### Move event to another calendar

```json
{
"tool": "move_event",
"input": {
"sourceCalendarId": "primary",
"eventId": "abc123",
"destinationCalendarId": "[email protected]",
"sendUpdates": "all"
}
}
```

### Duplicate an event

```json
{
"tool": "duplicate_event",
"input": {
"eventId": "abc123",
"newStart": {
"dateTime": "2024-01-22T14:00:00-03:00",
"timeZone": "America/Sao_Paulo"
},
"newEnd": {
"dateTime": "2024-01-22T15:00:00-03:00",
"timeZone": "America/Sao_Paulo"
}
}
}
```

## Project Structure

```
google-calendar/
├── server/
│ ├── main.ts # Entry point with OAuth
│ ├── constants.ts # API URLs and constants
│ ├── lib/
│ │ ├── google-client.ts # API client
│ │ └── types.ts # TypeScript types
│ └── tools/
│ ├── index.ts # Exports all tools
│ ├── calendars.ts # Calendar tools
│ ├── events.ts # Event tools
│ ├── freebusy.ts # Availability tool
│ └── advanced.ts # Advanced tools (move, find slots, duplicate)
├── app.json # MCP configuration
├── package.json
├── tsconfig.json
└── README.md
```

## OAuth Scopes

This MCP requests the following scopes:

- `https://www.googleapis.com/auth/calendar` - Full calendar access
- `https://www.googleapis.com/auth/calendar.events` - Event management

## License

MIT
12 changes: 12 additions & 0 deletions google-calendar/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"scopeName": "google",
"name": "google-calendar",
"connection": {
"type": "HTTP",
"url": "https://sites-google-calendar.decocache.com/mcp"
},
"description": "Integrate and manage your Google Calendar. Create, edit and delete events, check availability and sync your calendars.",
"icon": "https://assets.decocache.com/mcp/b5fffe71-647a-461c-aa39-3da07b86cc96/Google-Meets.svg",
"unlisted": false
}

28 changes: 28 additions & 0 deletions google-calendar/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "google-calendar",
"version": "1.0.0",
"description": "Google Calendar MCP Server - Manage calendars and events",
"private": true,
"type": "module",
"scripts": {
"dev": "bun run --hot server/main.ts",
"build:server": "NODE_ENV=production bun build server/main.ts --target=bun --outfile=dist/server/main.js",
"build": "bun run build:server",
"publish": "cat app.json | deco registry publish -w /shared/deco -y",
"check": "tsc --noEmit"
},
"dependencies": {
"@decocms/runtime": "^1.0.3",
"zod": "^3.24.3"
},
"devDependencies": {
"@decocms/mcps-shared": "workspace:*",
"@modelcontextprotocol/sdk": "1.25.1",
"deco-cli": "^0.28.0",
"typescript": "^5.7.2"
},
"engines": {
"node": ">=22.0.0"
}
}

55 changes: 55 additions & 0 deletions google-calendar/server/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Google Calendar API constants and configuration
*/

export const GOOGLE_CALENDAR_API_BASE =
"https://www.googleapis.com/calendar/v3";

// API Endpoints
export const ENDPOINTS = {
CALENDAR_LIST: `${GOOGLE_CALENDAR_API_BASE}/users/me/calendarList`,
CALENDARS: `${GOOGLE_CALENDAR_API_BASE}/calendars`,
EVENTS: (calendarId: string) =>
`${GOOGLE_CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events`,
EVENT: (calendarId: string, eventId: string) =>
`${GOOGLE_CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`,
QUICK_ADD: (calendarId: string) =>
`${GOOGLE_CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/quickAdd`,
FREEBUSY: `${GOOGLE_CALENDAR_API_BASE}/freeBusy`,
};

// Default calendar ID
export const PRIMARY_CALENDAR = "primary";

// Default pagination
export const DEFAULT_MAX_RESULTS = 50;

// Event colors (Google Calendar color IDs)
export const EVENT_COLORS = {
LAVENDER: "1",
SAGE: "2",
GRAPE: "3",
FLAMINGO: "4",
BANANA: "5",
TANGERINE: "6",
PEACOCK: "7",
GRAPHITE: "8",
BLUEBERRY: "9",
BASIL: "10",
TOMATO: "11",
} as const;

// Event visibility options
export const EVENT_VISIBILITY = {
DEFAULT: "default",
PUBLIC: "public",
PRIVATE: "private",
CONFIDENTIAL: "confidential",
} as const;

// Event status
export const EVENT_STATUS = {
CONFIRMED: "confirmed",
TENTATIVE: "tentative",
CANCELLED: "cancelled",
} as const;
17 changes: 17 additions & 0 deletions google-calendar/server/lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Env } from "../../shared/deco.gen.ts";

/**
* Get Google OAuth access token from environment context
* @param env - The environment containing the mesh request context
* @returns The OAuth access token
* @throws Error if not authenticated
*/
export const getGoogleAccessToken = (env: Env): string => {
const authorization = env.MESH_REQUEST_CONTEXT?.authorization;
if (!authorization) {
throw new Error(
"Not authenticated. Please authorize with Google Calendar first.",
);
}
return authorization;
};
Loading
Loading