Skip to main content
Glama

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


Related MCP server: calendar-mcp

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.

  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

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Naim-Howlader/google-calendar-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server