google-calendar-mcp

google-calendar-mcp

A production-ready MCP server that lets AI assistants interact with your personal Google Calendar using the Google Calendar API and OAuth 2.0.

Category
Visit Server

README

google-calendar-mcp

License: MIT Node.js MCP

A production-ready Model Context Protocol (MCP) server that lets AI assistants interact with your personal Google Calendar using the Google Calendar API and OAuth 2.0.

Connect it to Cursor, Claude Desktop, VS Code, or any MCP client that supports stdio transport. Each user runs a local copy with their own Google credentials.

Security: Never commit .env or real OAuth tokens. See SECURITY.md.


Features

  • 7 MCP tools — list calendars, list / search / create / update / delete events, and free/busy queries
  • OAuth 2.0 with refresh tokens — access tokens refresh automatically; you never paste a short-lived access token
  • Zod validation on every tool input
  • Structured logging to stderr (tool name, duration, API errors)
  • Graceful errors — 401, 403, 404, 429, network failures, and expired refresh tokens return readable MCP errors without crashing
  • stdio transport — works with local MCP hosts out of the box

Architecture overview

┌─────────────────────┐     stdio (JSON-RPC)      ┌──────────────────────────┐
│  MCP Client         │ ◄───────────────────────► │  google-calendar-mcp     │
│  Cursor / Claude /  │                           │  McpServer + tools       │
│  VS Code            │                           │  auth.ts → OAuth2        │
└─────────────────────┘                           │  calendar.ts → API calls │
                                                  └────────────┬─────────────┘
                                                               │
                                                               ▼
                                                  ┌──────────────────────────┐
                                                  │  Google Calendar API v3  │
                                                  │  (googleapis + refresh)  │
                                                  └──────────────────────────┘
  1. The MCP client spawns this server as a child process.
  2. Credentials are loaded from .env (or the client env block).
  3. googleapis refreshes access tokens using your refresh token as needed.
  4. Tools in src/tools/ call shared helpers in src/calendar.ts (no duplicated API logic).

This is a single-user, local server—not a multi-tenant cloud service.


Screenshots

Place screenshots under docs/images/ after publishing if desired.

Cursor MCP connected Example tool result
Cursor MCP List events

(Image paths are placeholders until you add screenshots.)


Tech stack

Technology Role
TypeScript Strict-mode application language
Node.js 18+ Runtime
@modelcontextprotocol/sdk MCP server (McpServer, registerTool, StdioServerTransport)
googleapis Official Google Calendar client
zod Tool input schemas
dotenv Local environment loading
tsx Development runner

Docker is not provided. This server uses stdio; MCP clients typically start a local Node process. Packaging it in Docker is unnecessary for the supported setup.


Requirements

  • Node.js 18 or later
  • A Google Cloud project
  • Google Calendar API enabled
  • OAuth 2.0 client ID and secret
  • A refresh token with Calendar access
  • An MCP-compatible client (Cursor, Claude Desktop, VS Code, etc.)

Installation

git clone https://github.com/[your-org]/google-calendar-mcp.git
cd google-calendar-mcp
npm install

Copy the environment template:

cp .env.example .env

Fill in your credentials (see Google Cloud OAuth setup below). Never commit .env.


Environment variables

Variable Required Description
GOOGLE_CLIENT_ID Yes OAuth 2.0 client ID from Google Cloud Console
GOOGLE_CLIENT_SECRET Yes OAuth 2.0 client secret
GOOGLE_REFRESH_TOKEN Yes Long-lived refresh token from the OAuth consent flow
DEFAULT_CALENDAR_ID No Default calendar when a tool omits calendarId (default: primary)

Example .env (placeholders only):

GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REFRESH_TOKEN=your-refresh-token
DEFAULT_CALENDAR_ID=primary

Google Cloud OAuth setup

Follow these steps if you have never used Google Cloud. Screens and labels change occasionally; use the current Console navigation that matches each step.

1. Create a Google Cloud project

  1. Open Google Cloud Console.
  2. Click the project selector at the top → New Project.
  3. Enter a name (for example google-calendar-mcp) → Create.
  4. Select the new project.

2. Enable the Google Calendar API

  1. Go to APIs & ServicesLibrary.
  2. Search for Google Calendar API.
  3. Open it → click Enable.

3. Configure the OAuth consent screen

  1. Go to APIs & ServicesOAuth consent screen.
  2. Choose External (unless you use Google Workspace Internal) → Create.
  3. Fill in App name, User support email, and Developer contact.
  4. Save and continue through Scopes / Test users as prompted.
  5. Under Test users (while the app is in Testing), add the Google account whose calendar you will use.

Important: In Testing mode, refresh tokens may expire after 7 days. For personal long-term use, keep yourself as a test user or publish the app when eligible. Revoking access or resetting the OAuth client also invalidates tokens.

4. Create an OAuth client ID

  1. Go to APIs & ServicesCredentials.

  2. Click Create credentialsOAuth client ID.

  3. Application type:

    • Web application is easiest with the OAuth Playground (recommended below), or
    • Desktop app if you prefer another flow later.
  4. Name the client (for example calendar-mcp-local).

  5. If using Web application, under Authorized redirect URIs add:

    https://developers.google.com/oauthplayground
    
  6. Click Create. Copy the Client ID and Client secret into your .env file.

5. Required OAuth scope

This server needs:

https://www.googleapis.com/auth/calendar

That scope allows reading and writing calendar data for the authorized account.

6. Obtain a refresh token (OAuth 2.0 Playground)

  1. Open Google OAuth 2.0 Playground.
  2. Click the gear icon (top right).
  3. Check Use your own OAuth credentials.
  4. Paste your Client ID and Client secret → close the dialog.
  5. In the left list, expand Calendar API v3 and select
    https://www.googleapis.com/auth/calendar
    (or paste that scope in the custom scope box).
  6. Click Authorize APIs and sign in with your test user account. Grant the permissions.
  7. Click Exchange authorization code for tokens.
  8. Copy the refresh_token value (not the access token) into .env as GOOGLE_REFRESH_TOKEN.

If you do not see a refresh token, revoke the app at Google Account permissions and repeat with your own credentials and “offline” access (Playground does this when configured as above).

7. First-time authentication check

From the project root:

npm run build
npm run dev

On success, stderr should include structured logs such as:

  • OAuth2 client initialized
  • Authentication validated successfully
  • google-calendar-mcp server connected and ready

Then stop with Ctrl+C. For day-to-day use, configure an MCP client so it starts the server for you (next sections). You do not need to keep a terminal open after the client is configured.


Running locally

Build and start

npm run build
npm start

Development (no build step)

npm run dev

Type-check only

npm run typecheck

The process listens on stdio. Running it alone in a terminal will look idle after startup—that is expected. Use an MCP client or the MCP Inspector:

npx @modelcontextprotocol/inspector node dist/index.js

Configuration

Use absolute paths. Prefer built dist/index.js after npm run build. Secrets can live in .env (loaded by the server) and/or in the client env block.

Cursor

Project file: .cursor/mcp.json (or Cursor global MCP settings). See also examples/mcp-cursor.json.

{
  "mcpServers": {
    "google-calendar": {
      "command": "node",
      "args": ["/absolute/path/to/google-calendar-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "your-client-secret",
        "GOOGLE_REFRESH_TOKEN": "your-refresh-token",
        "DEFAULT_CALENDAR_ID": "primary"
      }
    }
  }
}

Restart Cursor and confirm the server is connected under Settings → MCP.

Claude Desktop

Config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "google-calendar": {
      "command": "node",
      "args": ["/absolute/path/to/google-calendar-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "your-client-secret",
        "GOOGLE_REFRESH_TOKEN": "your-refresh-token",
        "DEFAULT_CALENDAR_ID": "primary"
      }
    }
  }
}

VS Code

Add under your MCP / Copilot MCP server settings (exact key may vary by extension):

{
  "mcp": {
    "servers": {
      "google-calendar": {
        "command": "node",
        "args": ["/absolute/path/to/google-calendar-mcp/dist/index.js"],
        "env": {
          "GOOGLE_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
          "GOOGLE_CLIENT_SECRET": "your-client-secret",
          "GOOGLE_REFRESH_TOKEN": "your-refresh-token"
        }
      }
    }
  }
}

Available MCP tools

Tool Description
list_calendars Returns every calendar available to the authenticated user
list_events Lists events in a time range (optional filters)
search_events Free-text search via Google’s q parameter
create_event Creates an event; returns created event details including id
update_event Partially updates an event (only supplied fields)
delete_event Deletes an event
free_busy Returns busy periods for one or more calendars

Example prompts

Ask your AI client natural language such as:

  • “List my calendars.”
  • “What meetings do I have tomorrow?”
  • “Search my calendar for dentist.”
  • “Create a 1-hour event called Team Sync tomorrow at 10am.”
  • “Am I free Friday afternoon?”

See examples/prompts.md for more.

Sample tool request

{
  "name": "list_events",
  "arguments": {
    "timeMin": "2026-07-14T00:00:00Z",
    "timeMax": "2026-07-21T00:00:00Z",
    "maxResults": 5,
    "orderBy": "startTime"
  }
}

Sample tool response (illustrative only)

[
  {
    "id": "abc123example",
    "summary": "Team Sync",
    "start": { "dateTime": "2026-07-15T10:00:00-07:00" },
    "end": { "dateTime": "2026-07-15T11:00:00-07:00" },
    "status": "confirmed",
    "htmlLink": "https://www.google.com/calendar/event?eid=example"
  }
]

More samples: examples/sample-responses.md.


Project structure

google-calendar-mcp/
├── src/
│   ├── index.ts              # Entry — stdio transport
│   ├── server.ts             # McpServer factory and tool registration
│   ├── auth.ts               # OAuth2 client and token refresh
│   ├── calendar.ts           # Google Calendar API wrapper
│   ├── types.ts              # Shared TypeScript types
│   ├── utils.ts              # Logging, error handling, helpers
│   └── tools/
│       ├── listCalendars.ts
│       ├── listEvents.ts
│       ├── searchEvents.ts
│       ├── createEvent.ts
│       ├── updateEvent.ts
│       ├── deleteEvent.ts
│       └── freeBusy.ts
├── examples/                 # Sample configs and prompts (no secrets)
├── .env.example
├── package.json
├── tsconfig.json
├── LICENSE
├── CONTRIBUTING.md
├── SECURITY.md
├── CODE_OF_CONDUCT.md
├── CHANGELOG.md
└── README.md

Development workflow

npm install
cp .env.example .env   # add your credentials
npm run typecheck
npm run build
npm run dev            # or connect via MCP Inspector / Cursor

Contributions welcome—see CONTRIBUTING.md.


Troubleshooting

Problem What to try
Missing environment variables Copy .env.example.env and set all three Google variables
Authentication failed (401) / invalid refresh token Re-run OAuth Playground; ensure Client ID matches the token; revoke and re-authorize if needed
Permission denied (403) Enable Google Calendar API; confirm scope includes calendar; ensure you are a consent screen test user
Rate limit (429) Wait and retry; lower maxResults
redirect_uri_mismatch in Playground Add https://developers.google.com/oauthplayground to authorized redirect URIs
MCP client cannot connect Use absolute paths; run npm run build first; ensure Node 18+ is on PATH
Server seems frozen after start Normal for stdio—clients must spawn and speak the protocol
Refresh token stops working after ~7 days App is in Testing mode—see OAuth consent screen notes above

Logs are written as JSON lines to stderr. Do not log secrets.


FAQ

Do I need to keep a terminal open for Cursor?
No. Once MCP is configured, Cursor starts and stops the server automatically.

Is this multi-user?
No. One process uses one set of credentials and one Google account.

Can I publish my .env?
Never. Treat client secret and refresh token like passwords.

Can I use a service account?
This project is built for user OAuth with a refresh token, not service accounts.

Why no Docker?
MCP stdio clients spawn a local command. Running Node directly is the supported path.


Contributing

See CONTRIBUTING.md and CODE_OF_CONDUCT.md.


License

This project is licensed under the MIT License.


Acknowledgements

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured