Building Google Calendar MCP Server for Cursor IDE Integration

4 min readSargon Piraev

Learn how to build a production-ready MCP server that integrates Google Calendar API with Cursor IDE for seamless workflow automation

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:

  1. 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
  1. 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
  1. 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...