Motivation
As a daily Cursor IDE user, I'm constantly looking for ways to enhance my development workflow. I love how Cursor's AI capabilities help me code faster, but I wanted to take it further by integrating my Google Calendar directly into the IDE. Building an MCP server seemed like the perfect opportunity to both improve my workflow and get hands-on experience with the MCP protocol.
The idea came to me during a particularly busy week of juggling coding and meetings. I realized that being able to check my calendar and create events without leaving Cursor would be incredibly valuable. Plus, implementing an MCP server would help me better understand how to build integrations for Cursor IDE.
Implementation
Let's walk through building a production-ready MCP server for Google Calendar integration. I'll share the exact steps and code patterns I used.
Project Structure
First, I set up the project structure:
mcp-server/
├── src/
│ ├── server.ts
│ └── main.ts
├── package.json
├── tsconfig.json
└── .env
Installing Dependencies
The core dependencies needed for the server:
{
"dependencies": {
"@google-cloud/local-auth": "^2.1.0",
"googleapis": "^105.0.0",
"zod": "^3.21.4",
"axios": "^1.4.0",
"@cursor-protocol/mcp-server": "^0.4.1",
"dotenv": "^16.0.3"
}
}
Install them with:
npm install
Environment Setup
In server.ts, I first set up environment parsing using Zod:
import { z } from 'zod';
import dotenv from 'dotenv';
const envSchema = z.object({
GOOGLE_CLIENT_ID: z.string(),
GOOGLE_CLIENT_SECRET: z.string(),
GOOGLE_REFRESH_TOKEN: z.string()
});
dotenv.config();
const env = envSchema.parse(process.env);
Creating the Google Calendar Client
Next, I created an authenticated Google Calendar client:
import { google } from 'googleapis';
const oauth2Client = new google.auth.OAuth2(
env.GOOGLE_CLIENT_ID,
env.GOOGLE_CLIENT_SECRET
);
oauth2Client.setCredentials({
refresh_token: env.GOOGLE_REFRESH_TOKEN
});
const calendar = google.calendar({
version: 'v3',
auth: oauth2Client
});
Setting Up the MCP Server
Now for the core MCP server setup:
import { McpServer } from '@cursor-protocol/mcp-server';
const mcpServer = new McpServer({
name: 'google-calendar',
version: '1.0.0'
});
Implementing Calendar Tools
Here's an example tool implementation for listing upcoming events:
const ListEventsSchema = z.object({
maxResults: z.number().optional().default(10)
});
mcpServer.tool({
name: 'list_upcoming_events',
description: 'Lists upcoming calendar events',
parameters: ListEventsSchema,
handler: async (params) => {
const response = await calendar.events.list({
calendarId: 'primary',
timeMin: new Date().toISOString(),
maxResults: params.maxResults,
singleEvents: true,
orderBy: 'startTime'
});
return response.data.items?.map(event => ({
summary: event.summary,
start: event.start?.dateTime || event.start?.date,
end: event.end?.dateTime || event.end?.date
}));
}
});
Main Entry Point
In main.ts, I added the server startup code:
import { server } from './server';
const port = 3000;
server.listen(port, () => {
console.log(`Google Calendar MCP server running on port ${port}`);
});
Usage
Here's how to use the Google Calendar MCP server with Cursor IDE:
Global Installation
Install the package globally:
npm install -g @sargon/google-calendar-mcp
Cursor Configuration
Add this entry to your Cursor IDE's mcp.json:
{
"servers": {
"google-calendar": {
"command": "google-calendar-mcp",
"url": "http://localhost:3000"
}
}
}
Example Prompts
Here are some example prompts you can use in Cursor:
- List upcoming meetings:
What meetings do I have scheduled for today?
// Response: Fetching your upcoming events...
// - Team Standup at 10:00 AM
// - Client Meeting at 2:00 PM
// - Project Review at 4:30 PM
- Create a new event:
Schedule a meeting with the engineering team for tomorrow at 3pm
// Response: Created new event "Engineering Team Sync"
// Date: Tomorrow, 3:00 PM - 4:00 PM
// Attendees will receive calendar invites
- Check availability:
Am I free next Tuesday afternoon?
// Response: Checking your calendar for next Tuesday...
// You have 2 conflicts:
// - 1:00 PM - 2:00 PM: Weekly Planning
// - 4:00 PM - 5:00 PM: Product Demo
// Available slots: 2:00 PM - 4:00 PM
How It Works
Here's a sequence diagram showing how the integration works:
Rendering diagram...