Skip to main content
Glama
Parth-suryawanshi

mcp-google-workspace-agent

Google Calendar-Sheet Assistant — Full Edition (MCP + LLM)

A complete Google Calendar assistant. Not just "create a meeting" — every common calendar task, exposed as an MCP tool, chosen automatically by an LLM based on what you type.

        User
         │
         ▼
"Move my 3 PM meeting to 5 PM"
         │
         ▼
   OpenAI / GPT-OSS-120B
         │
(Decides which tool(s) to call — can chain more than one)
         │
         ▼
   MCP Client (Python)          ← client.py
         │
 Calls tool(s) through MCP protocol
         │
         ▼
Google Calendar MCP Server       ← server.py  (14 tools)
         │
 Executes Google Calendar API    ← calendar_utils.py
         │
         ▼
     Google Calendar
         │
         ▼
Success / Event Details
         │
         ▼
        User

All supported tasks

Task

Example prompt

Tool used

Create event

"Schedule a meeting tomorrow at 3 PM."

schedule_event

Update event

"Move my 3 PM meeting to 5 PM."

search_events/list_eventsupdate_event

Delete event

"Cancel tomorrow's interview."

search_eventscancel_event

List events

"What are my meetings today?"

daily_agenda

Search events

"Find all AI meetings this month."

search_events

Get event details

"Show details of my client meeting."

search_eventsget_event

Check free/busy

"Am I free between 2 PM and 4 PM?"

check_freebusy

Daily agenda

"What's on my schedule today?"

daily_agenda

Weekly agenda

"Show this week's calendar."

weekly_agenda

Monthly agenda

"Show my August meetings."

monthly_agenda

Recurring events

"Every Monday 10 AM team standup."

schedule_event (with recurrence)

Invite attendees

"Create meeting and invite abc@gmail.com."

schedule_event (with attendees)

Add Google Meet link

"Create an online meeting."

schedule_event (with add_meet_link)

Set reminders

"Remind me 30 minutes before."

schedule_event/update_event (with reminder_minutes_before)

Add location

"Meeting at Baner Office."

schedule_event (with location)

Add description

"Agenda: Sprint Planning."

schedule_event (with description)

List calendars

"Show all my calendars."

list_calendars

Move event

"Move this event to my Work calendar."

move_event

Import events

Bringing in an event from another system

import_event

Watch calendar changes

Trigger the agent on new events

watch_calendar (needs a public webhook URL — see note below)

Related MCP server: gworkspace-mcp

Project structure

google-calendar-sheet-mcp-/
├── server.py            # MCP server — 15 Calendar tools + 8 Sheets tools
├── client.py            # MCP client — LLM picks tool(s), can chain multiple calls
├── calendar_utils.py     # All Google Calendar API logic + OAuth (token.json)
├── sheets_utils.py        # All Google Sheets API logic + OAuth (token_sheets.json)
├── requirements.txt
├── .env.example
└── README.md

Setup

1. Google Cloud (one-time)

  1. Google Cloud Console → create/select a project.

  2. APIs & Services → Library → enable Google Calendar API AND Google Sheets API (search + enable both, same project).

  3. OAuth consent screen → External → add your email as a test user.

  4. Credentials → Create Credentials → OAuth client IDDesktop app.

  5. Download JSON → rename to credentials.json → place next to server.py. (This one file is reused by both calendar_utils.py and sheets_utils.py.)

2. Install

cd AI-AGENT
python3 -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate
pip install -r requirements.txt

3. Configure

cp .env.example .env
# add GROQ_API_KEY (https://console.groq.com/keys)

4. Run

python3 client.py

First run opens a browser to authorize Calendar access (saves token.json). The first time you ask it to do anything with Sheets, a second browser prompt appears — authorizing Sheets access separately (saves token_sheets.json). This is expected: Calendar and Sheets are different permissions, so they get separate consent + separate token files, even though both use the same credentials.json app identity.

Google Sheets — setup notes & example prompts

Every Sheets tool needs a spreadsheet_id — the long string in a sheet's URL, between /d/ and /edit:

https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUvWxYz/edit
                                        └──────── this part ────────┘

Example prompts:

  • "Create a new spreadsheet called 'Q3 Leads'." → create_spreadsheet

  • "In spreadsheet [id], what's in Sheet1 rows 1 to 10?" → read_sheet

  • "Add a row to spreadsheet [id]: Priya, priya@email.com, Contacted" → append_sheet_row

  • "Overwrite A1:B2 in [id] with these values..." → write_sheet

  • "What tabs does spreadsheet [id] have?" → list_sheet_tabs

  • "Add a new tab called 'August' to [id]." → add_sheet_tab

  • "Clear rows 2 to 50 in Sheet1 of [id]." → clear_sheet_range

  • "Give me the title and link for spreadsheet [id]." → get_spreadsheet_info

Sharing note: the Google account you authorized with (whichever one created token_sheets.json) needs edit access to any spreadsheet you ask it to read/write — either it owns the sheet, or someone shared it with that account.

How multi-step requests work

Some tasks need more than one tool call — e.g. "Move my 3 PM meeting to 5 PM" requires first finding the event (no id was given), then updating it. client.py handles this with a loop: it keeps letting the LLM call tools back-to-back (find → then act) until the LLM has enough information to give you a final plain-language answer. You'll see each intermediate tool call printed, e.g.:

You: Move my 3 PM meeting to 5 PM
[client] LLM chose tool: search_events({'query': '3 PM'})
[client] LLM chose tool: update_event({'event_id': 'abc123', 'start_time': '...', 'end_time': '...'})

Assistant: Done — moved your meeting to 5:00–5:30 PM today.

Recurring events — how RRULE works

schedule_event's recurrence argument takes standard iCalendar RRULE strings. The LLM constructs these automatically, but for reference:

  • Every Monday: RRULE:FREQ=WEEKLY;BYDAY=MO

  • Every weekday: RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR

  • Every day for 10 occurrences: RRULE:FREQ=DAILY;COUNT=10

  • Every month on the 1st: RRULE:FREQ=MONTHLY;BYMONTHDAY=1

Watch calendar changes — important note

watch_calendar sets up Google push notifications, but Google will only send them to a public HTTPS URL you control — not localhost. For local development:

  1. Run a tiny webhook receiver (Flask/FastAPI) that logs/handles the POST Google sends on changes.

  2. Expose it publicly with a tunnel tool (e.g. ngrok http 8000).

  3. Call watch_calendar with that public https://...ngrok.../webhook URL.

  4. The subscription expires (Google enforces a max TTL, typically up to ~7 days) — re-run watch_calendar periodically (e.g. a daily cron job) to keep it alive.

This part is the most "production infrastructure"-heavy feature here — the other 13 tools work immediately with no extra hosting required.

Testing the server alone (no LLM)

npx @modelcontextprotocol/inspector python3 server.py

Lets you call any of the 14 tools directly from a browser UI to confirm the Calendar integration works before wiring up chat.

Troubleshooting

Problem

Fix

FileNotFoundError: credentials.json not found

Complete Google Cloud setup step 1–5

invalid_grant / token errors

Delete token.json, re-run to re-authorize

LLM never calls a tool

Check OPENAI_API_KEY in .env

Update/cancel says "event not found"

The LLM needs the real event_id — make sure it searched/listed first

Wrong timezone on events

Set CALENDAR_TIMEZONE in .env

Recurring event didn't repeat as expected

Double check the RRULE the LLM generated — ask it to explain the rule if unsure

Related MCP Connectors

Related MCP Servers