Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.mmedum/google-calendar-mcp

MCPB · GOOGLE-CALENDAR-MCP_3.1.0.MCPB

Google Calendar over MCP: calendars, events, recurrence and availability.

+4 this week 64 Trust /100

Last scanned (23 hours ago)

Scores higher than 99% of MCPB servers

Category Productivity and Notes

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security0
  • No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.Unverified
  • Known CVEs could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).Unverified
  • Install-script risk not yet assessed.Unverified
  • Dependency health could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).Unverified
Provenance & Transparency100
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to mmedum/google-calendar-mcp). View diagnostics → Pass
  • Clear OSI-approved license (Apache-2.0).Pass
  • Actively maintained (last published 12 days ago).Pass
  • Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability74
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 10761 tokens (~538/item across 20 items; 19 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management87
  • Stability observed for 26 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 19 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 21 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass

Unverified: 1 category

A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 22 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 83 to 87. That category is still filling its 30-day observation window: 25 days of observed history at the previous scan, 26 at this one. The score rises as the window fills, whether or not the server changes.

  • 20 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 77 to 80. That category is still filling its 30-day observation window: 23 days of observed history at the previous scan, 24 at this one. The score rises as the window fills, whether or not the server changes.

  • 18 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 70 to 73. That category is still filling its 30-day observation window: 21 days of observed history at the previous scan, 22 at this one. The score rises as the window fills, whether or not the server changes.

  • 16 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 63 to 67. That category is still filling its 30-day observation window: 19 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.

  • 14 Oct 26 +40
    • Injection markers: unverified → pass ▲ security
    • Schema quality: 410 → 538 ▼ functional
    • Tool coverage: unverified → 100 ▲ functional
    • Schema quality: unverified → 100 ▲ functional
    • Stability: unverified → 0.60 ▲ functional
    • MCP protocol: unverified → pass ▲ functional
    • Package version: 3.0.1 → 3.1.0 functional
  • 12 Oct 26 +11
    • Provenance: unverified → pass ▲ security
    • The attested source repository moved: mmedum/google-calendar-mcp security
    • Security disclosure: unverified → pass ▲ functional
  • 11 Oct 26 −48
    • Stability: 0.37 → unverified ▼ security
    • Tool safety: pass → unverified ▼ security
    • Provenance: pass → unverified ▼ security
    • The attested source repository moved: mmedum/google-calendar-mcp security
    • Schema quality: 100 → unverified ▼ functional
    • Security disclosure: pass → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • Capabilities: pass → unverified ▼ functional
    • Package version: 3.0.1 → 3.1.0 functional
  • 7 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 30 to 37. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 22 Oct 2026 · Analysed mcpb/https://github.com/mmedum/google-calendar-mcp/releases/download/v3.1.0/google-calendar-mcp_3.1.0.mcpb@3.1.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem mcpb
Reason Verified
Discovered via GitHub artifact attestations
Source repo mmedum/google-calendar-mcp
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/mmedum/google-calendar-mcp/.github/workflows/release.yml@refs/tags/v3.1.0
Rekor log index 3172014946
Predicate type SLSA build provenance https://slsa.dev/provenance/v1
Subject digest sha256:e56204b7416e170e54ca17d769e78f58821b362b5def9ebcd7efc178873cc564

Background: How many MCP packages publish verified provenance →

MCP tools · 19 exposed · ~10,262 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
cancel_event ~713

Cancel an event, or one occurrence of a repeating one. A whole event is deleted; one occurrence is marked canceled, which is how a single date leaves a series — the result says which of the two happened. Google keeps the record either way, and list_events with show_canceled still shows it. `scope` is REQUIRED when the event repeats, and there is no default because the same words mean three different things: `instance` changes one occurrence, `series` changes all of them, and `this_and_following` changes this occurrence and every later one. Name the occurrence with the occurrence's own id, or with the series id plus `original_start` — the scheduled start, which list_instances reports, and which still identifies an occurrence somebody has moved. With `this_and_following` the series simply ends before this occurrence, which is one call rather than the two an update takes. `notify` is REQUIRED whenever the write can reach another person, and this server has no default in either direction: `none` asks Google to email nobody, `external_only` emails the guests outside your own organization, `all` emails every guest. `none` is refused outright when a guest is outside your organization, because such a guest may have no Google Calendar for the event to appear in and email is then the only way they can learn of it. Whatever you pass, the result says what was ASKED FOR — Google reports nothing about what arrived, and `none` is not a promise of silence. Read that rule twice here: canceling with no notification removes the meeting from YOUR calendar and leaves it on your guests'. They will still turn up. Every write is a patch under If-Match, so it is refused as `[stale]` rather than overwriting somebody who changed this first. Pass `etag` from the get_event you decided on to be held to that exact version; pass `force: true` only when you genuinely mean "whatever it says now". Without `etag`, a write refused that way is read again and made once more if nothing it changes, reache…

NameTypeReqDescription
calendarstringyesThe calendar the event is on.
dry_runboolean–Report what would be canceled and who would be emailed, without writing.
etagstring–The etag from the get_event you decided on.
event_idstringyesThe event id, or the series id when original_start names the occurrence.
forceboolean–Cancel with If-Match: * rather than being refused if somebody changed it first.
notifystring–Who Google is asked to email: none, external_only or all. Required when the event has guests — with none, the guests keep the meeting.
original_startstring–The occurrence's SCHEDULED start, from list_instances.
scopestring–Required when the event repeats: instance, series or this_and_following.
time_zonestring–IANA zone to read original_start and show the times in.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarstringyes–
changesnull|array––
dry_runboolean––
etagstring––
eventnull|object––
notesnull|array––
notificationstringyes–
scopestring––
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

check_availability ~628

When people are busy, and when they are free, in a window. `from` and `to` are required and take either a yyyy-mm-dd date or an RFC3339 timestamp. A bare date means that whole day in the resolved zone, so from and to on the same date is that one day. Resolve relative expressions like "next Tuesday" yourself before calling: this server does not guess, and the result always echoes the absolute window and the zone it used so you can check the resolution. Times are shown in `time_zone` if you pass one, otherwise the calendar's own zone, otherwise the zone in the account's Calendar settings. The result names which of the three it used. This server never falls back to the machine's own clock zone. This asks Google's free/busy service rather than listing events, which matters: it sees busy time on calendars whose events you cannot read, and it respects events marked "free", so a list of events is not the same answer. A calendar that could not be read comes back as UNKNOWN, never as free — do not book over it. A group's address is answered for its members together, and is unknown if any of them is. The result also reports the gaps when nobody is busy; min_minutes drops the ones too short to use. working_from, working_to and working_days mask the gaps to a working week: a window is one interval, so "next week, 09:00 to 17:00" cannot be asked for as a window and would otherwise come back with a fifteen-hour gap every night. There is no default — without them every hour of the window counts, and the result always says which was used. Calendars are asked in batches of 50, and the result says how many requests that took.

NameTypeReqDescription
calendarsnull|array–Calendar ids, email addresses or titles. Defaults to the account's primary calendar. An address works even for a calendar you cannot read, and may be a mailbox such as "Sample Person" <person@example…
fromstringyesStart of the window: yyyy-mm-dd or RFC3339. Required.
min_minutesinteger–Ignore free gaps shorter than this many minutes.
time_zonestring–IANA zone to read the window and show the times in.
tostringyesEnd of the window: yyyy-mm-dd or RFC3339. Required.
working_daysnull|array–Weekdays to keep, as mon tue wed thu fri sat sun. Empty means every day; the server does not assume anybody's working week.
working_fromstring–Start of the working day as hh:mm local, e.g. 09:00. Pass it with working_to. No default: without it the whole window counts.
working_tostring–End of the working day as hh:mm local, e.g. 17:00. Must be later in the day than working_from; a shift crossing midnight is refused.
NameTypeReqDescription
api_requestsintegeryes–
calendarsnull|arrayyes–
freenull|arrayyes–
free_computed_fromintegeryes–
min_minutesinteger––
time_zonestringyes–
time_zone_sourcestringyes–
unknown_calendarsintegeryes–
windowobjectyes–
working_hoursstring––

No examples provided.

create_calendar ~245

Create a new calendar of your own. You are its owner, it appears in your calendar list, and nobody else can see it until you share it — use share_calendar for that. It is created in `time_zone` if you pass one, otherwise the zone in this account's Calendar settings; the result says which it used, and every time written to the calendar afterward is read against it. Creating a calendar is quota-counted by Google and deleting one does not give the quota back, so do not create one per task. `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have.

NameTypeReqDescription
descriptionstring–What it is for.
dry_runboolean–Report what would be created, without writing.
locationstring–Free text, such as a city or a building.
time_zonestring–IANA zone the calendar keeps, such as Europe/Copenhagen. Defaults to this account's own.
titlestringyesWhat the calendar is called, for everybody it is shared with. Required.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarobjectyes–
changesnull|array––
dry_runboolean––
notesnull|array––

No examples provided.

create_event ~1,611

Create an event. `start` and `end` are either two yyyy-mm-dd dates for an all-day event, where `end` is the LAST day and is included, or two RFC3339 timestamps for a timed one — never one of each, because a date is not a time. Times are written in `time_zone` if you pass one, otherwise the calendar's own zone; the result says which it used, and the zone is always sent alongside the timestamp so a repeating event keeps its wall-clock time across a daylight-saving change. `recurrence` takes RFC 5545 lines such as RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=10. `conference: true` asks Google for a Meet link. The link normally comes back with the event, but Google may still be making it — the result says which, and when it says the link is still being made, read the event again to get it rather than promising anybody a link. update_event's `add_conference` adds one to an event later. `optional_guests` invites people as optional; they are emailed like any guest, so they make notify required too. A room cannot be optional. An address may be bare or a mailbox such as "Sample Person" <person@example.com>, the way a mail server hands one over; only the address is used, and one entry holds one address. `popup_reminders` and `email_reminders` are minutes before the start, 0 to 40320, at most five in all. Either one replaces the whole set, so pass both to keep both kinds, and an empty list given alone means no reminders. `default_reminders: true` goes back to the calendar's own. Reminders are yours alone: Google keeps them per person, so they never notify a guest. `visibility` is default, public or private: private shows the details only to the guests, and public to everybody who can see the calendar. `guests_can_modify`, `guests_can_invite_others` and `guests_can_see_other_guests` say what a guest may do. `event_type` makes a status event, which only your primary calendar can hold: outOfOffice, focusTime or workingLocation. Out of office and focus time are timed, never all day, and alwa…

NameTypeReqDescription
auto_declinestring–Required for outOfOffice and focusTime, with no default: none, new (invitations that arrive for that time) or all (also the meetings you already accepted, which asks the person first).
calendarstring–The calendar id or title to create it on. Defaults to the account's primary calendar.
chat_statusstring–focusTime only: available or do_not_disturb, what Google Chat shows during it.
conferenceboolean–Ask Google for a Google Meet link. Usually in the answer; if it says the link is still being made, read the event again for it.
decline_messagestring–The message each organizer gets with a decline. outOfOffice and focusTime only, and not with auto_decline none.
default_remindersboolean–Use the calendar's own reminders, which is also what happens when no list is given.
descriptionstring–Longer text on the event.
dry_runboolean–Report what would be created and who would be emailed, without writing.
email_remindersnull|array–Email reminders for you, in minutes before the start, 0 to 40320. At most five reminders in all.
endstringyesEnd: for an all-day event the LAST day, included; for a timed one an RFC3339 timestamp. Must be the same kind as start. Required.
event_typestring–Make a status event on your primary calendar: outOfOffice, focusTime or workingLocation. Leave it out for an ordinary event.
free_not_busyboolean–Mark the time as free rather than busy, so it does not block availability.
guestsnull|array–Email addresses to invite. Passing any of these makes notify required.
guests_can_invite_othersnull|boolean–Whether guests may invite others. Google's default is true.
guests_can_modifynull|boolean–Whether guests may change the event. Google's default is false.
guests_can_see_other_guestsnull|boolean–Whether guests see the guest list. Google's default is true.
locationstring–Where it is.
notifystring–Who Google is asked to email: none, external_only or all. Required when the event has guests.
optional_guestsnull|array–Email addresses to invite as optional guests. They are emailed like any guest, so passing any makes notify required. A room cannot be optional.
popup_remindersnull|array–Popup reminders for you, in minutes before the start, 0 to 40320. Replaces the calendar's default reminders; an empty list given alone means none.
recurrencenull|array–RFC 5545 lines, such as RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=10.
roomsnull|array–Addresses of rooms or other resources to book. A room is not a guest, so it does not make notify required; an address here that is not a room's still counts as one.
startstringyesStart: yyyy-mm-dd for an all-day event, or RFC3339 for a timed one. Required.
time_zonestring–IANA zone the times are written in, such as Europe/Copenhagen. Defaults to the calendar's own.
titlestringyesWhat the event is called. Required.
visibilitystring–default, public or private. Private shows the details only to the guests.
working_locationstring–Required for workingLocation: home, office or custom.
working_location_labelstring–The office's name, or the place for custom, as Calendar shows it. Not with home.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarstringyes–
changesnull|array––
dry_runboolean––
etagstring––
eventnull|object––
notesnull|array––
notificationstringyes–
scopestring––
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

get_calendar ~82

One calendar in full: its description, time zone, your access level, and who else it is shared with. Use list_calendars to see every calendar; use this when you need the sharing list or are checking whether you may write somewhere.

NameTypeReqDescription
calendarstringyesThe calendar id, its title, or "primary" for the account's own calendar.
NameTypeReqDescription
calendarobjectyes–
default_remindersnull|object––
descriptionstring––
notestring––
sharingnull|array––

No examples provided.

get_event ~208

One event in full, including its guests and their responses, its recurrence rule if it has one, and its etag. Times are shown in `time_zone` if you pass one, otherwise the calendar's own zone, otherwise the zone in the account's Calendar settings. The result names which of the three it used. This server never falls back to the machine's own clock zone. It lists the files attached to the event with each one's Drive file id; this server never opens a file, so pass the id to a Drive server to read one. An event id is unique per calendar and not globally, so `calendar` is required alongside it. Ids come from list_events or search_events.

NameTypeReqDescription
calendarstringyesThe calendar the event is on. An event id is unique per calendar, not globally.
event_idstringyesThe event id, from list_events or search_events.
time_zonestring–IANA zone to show the times in.
NameTypeReqDescription
attachmentsnull|array––
attendeesnull|array––
eventobjectyes–
guests_can_invite_othersbooleanyes–
guests_can_modifybooleanyes–
guests_can_see_other_guestsbooleanyes–
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

get_settings ~66

The account's own Calendar settings: its time zone, which day the week starts on, and the color palette. The time zone here is the last fallback for every other tool, so read it when you need to know what "today" or "9am" means for this person.

Input schema present but exposes no named parameters.

NameTypeReqDescription
calendar_colorsobject––
event_colorsobject––
format_24_hourstring––
localestring––
time_zonestringyes–
week_startstring––

No examples provided.

list_calendars ~97

List the calendars this account can see, with each one's id, time zone and your access level. Start here: every other tool takes a calendar, the ids come from this list, and the time zone it reports is what dates and times elsewhere are read against. It is cheap. Use get_calendar for one calendar's description and who it is shared with.

NameTypeReqDescription
include_hiddenboolean–Include calendars hidden in the Calendar UI.
NameTypeReqDescription
calendarsnull|arrayyes–
countintegeryes–

No examples provided.

list_changes ~579

What changed on a calendar since you last looked. This is the only read that reports DELETIONS: a deleted event stops matching a window, so list_events cannot tell you it is gone, and this returns its id under deleted. Call it once with no sync_token to get a baseline and a token; pass that token next time and you get only what has changed since. The token comes back with the LAST page only. A baseline therefore pages all the way to the end to fetch one, and says how many rows it passed over on the way — they are covered by the token, not lost. An INCREMENTAL read stops at its budget instead and hands back no token, because every row there is a change you have not seen yet; continue with page_token and the same sync_token until the token arrives, and never store one you did not get. It takes no window, no search and no ordering: Google forbids all of them alongside a sync token, and deleted events are always included. If the token has expired the call fails [stale]; ask again with no sync_token and start over. updated_since asks instead for what changed since a moment, such as "since Monday": an RFC3339 time, or a yyyy-mm-dd date meaning the start of that day in time_zone, else the calendar's zone; the result echoes the instant it used. It cannot be combined with sync_token. Events deleted since then are always included. Google calls this the legacy way and says it can miss updates: an event whose only change was its reminders is not reported. Its last page hands back a sync token too, to follow the calendar from there; continue a read that stopped early with page_token and the same updated_since. A moment too far back fails [stale]; pass a later one.

NameTypeReqDescription
calendarstringyesThe calendar to check for changes.
max_eventsinteger–Cap on events returned. The server has its own budget and says when it truncated.
page_tokenstring–Continue a read that did not finish, from next_page_token, with the same calendar and the same sync_token or updated_since. The sync token arrives with the last page.
sync_tokenstring–A token from a previous call's sync_token. Leave it out the first time to get a baseline and a token. Opaque: never build or edit one.
time_zonestring–IANA zone to show the changed events in, and to read an updated_since date in.
updated_sincestring–Only what changed at or after this moment: RFC3339, or yyyy-mm-dd for the start of that day in time_zone, else the calendar's zone. Not with sync_token. The last page hands back a sync token to follo…
NameTypeReqDescription
api_requestsintegeryes–
baselinebooleanyes–
calendar_idstringyes–
calendar_namestring––
changednull|arrayyes–
completebooleanyes–
deletednull|arrayyes–
next_page_tokenstring––
skippedinteger––
sync_tokenstring––
time_zonestringyes–
time_zone_sourcestringyes–
updated_sincestring––

No examples provided.

list_events ~636

Read a schedule: the events on one or more calendars in a window. `from` and `to` are required and take either a yyyy-mm-dd date or an RFC3339 timestamp. A bare date means that whole day in the resolved zone, so from and to on the same date is that one day. Resolve relative expressions like "next Tuesday" yourself before calling: this server does not guess, and the result always echoes the absolute window and the zone it used so you can check the resolution. Times are shown in `time_zone` if you pass one, otherwise the calendar's own zone, otherwise the zone in the account's Calendar settings. The result names which of the three it used. This server never falls back to the machine's own clock zone. `expand` decides which shape you get, and the two are genuinely different: with expand=true (the default) a repeating event appears as each of its occurrences, which is what you want to answer "what is on this week". With expand=false it appears once, as a series with its recurrence rule, which is what you want before changing the whole series. Canceled events are hidden unless show_canceled is set. event_types keeps only some kinds of event, such as outOfOffice, and the result names the filter. ical_uid keeps only the event with that iCalendar UID, which is how to find the event an invitation email is about. Every occurrence of a repeating event shares one UID, so with expand you get each occurrence in the window. The window still applies: make it wide enough for a meeting that may have moved. Use search_events to find an event by text; use check_availability to find free time, because a list of events is not the same as being free.

NameTypeReqDescription
calendarsnull|array–Calendar ids or titles. Defaults to the account's primary calendar.
event_typesnull|array–Only events of these types: default, birthday, focusTime, fromGmail, outOfOffice, workingLocation. Leave it out for every type.
fromstringyesStart of the window: yyyy-mm-dd or RFC3339. Required.
ical_uidstring–Only the event with this iCalendar UID, such as the UID an invitation email carries. Every occurrence of a repeating event shares it.
max_eventsinteger–Cap on events returned. The server has its own budget and says when it truncated.
no_expandboolean–Return repeating events once as a series with its rule, instead of as each occurrence.
page_tokenstring–Continue a truncated read, from next_page_token, with the same arguments; a token is refused under another query.
show_canceledboolean–Include canceled events, which are hidden by default.
time_zonestring–IANA zone to read the window and show the times in, such as Europe/Copenhagen.
tostringyesEnd of the window: yyyy-mm-dd or RFC3339. Required. A bare date means the end of that day.
NameTypeReqDescription
api_requestsintegeryes–
calendarsnull|arrayyes–
event_typesnull|array––
eventsnull|arrayyes–
ical_uidstring––
matchedintegeryes–
next_page_tokenstring––
recurring_expandedbooleanyes–
shownintegeryes–
time_zonestringyes–
time_zone_sourcestringyes–
truncatedbooleanyes–
windowobjectyes–

No examples provided.

list_instances ~380

The occurrences of one repeating event. `event_id` is the SERIES id, which list_events reports as series_id on each occurrence — an occurrence's own id is not a series id. Pass both from and to for a window, or neither for the whole series. Times are shown in `time_zone` if you pass one, otherwise the calendar's own zone, otherwise the zone in the account's Calendar settings. The result names which of the three it used. This server never falls back to the machine's own clock zone. Each occurrence reports its own id, and says when it was moved from its scheduled time. Canceled occurrences are hidden unless show_canceled is set, and a canceled occurrence is how one date is removed from a series — so pass it when you need to know which dates are gone. Use get_event on the series id to see the recurrence rule itself.

NameTypeReqDescription
calendarstringyesThe calendar the series is on.
event_idstringyesThe repeating event's id. On an occurrence from list_events this is its series_id, not its own id.
fromstring–Start of the window: yyyy-mm-dd or RFC3339. Pass both from and to, or neither.
max_eventsinteger–Cap on occurrences returned. The server has its own budget and says when it truncated.
page_tokenstring–Continue a truncated read, from next_page_token, with the same arguments; a token is refused under another read.
show_canceledboolean–Include occurrences that were canceled, which is how single dates are removed from a series.
time_zonestring–IANA zone to show the occurrences in.
tostring–End of the window: yyyy-mm-dd or RFC3339. Pass both from and to, or neither.
NameTypeReqDescription
api_requestsintegeryes–
calendar_idstringyes–
canceled_hiddenbooleanyes–
instancesnull|arrayyes–
next_page_tokenstring––
series_idstringyes–
shownintegeryes–
time_zonestringyes–
time_zone_sourcestringyes–
titlestring––
truncatedbooleanyes–
windownull|object––

No examples provided.

list_sharing ~140

Who can see a calendar, and what each of them can see. Roles are explained rather than echoed, because `writerWithoutPrivateAccess` and `freeBusyReader` do not say what they mean. A rule reading ANYONE means the calendar is public to the whole internet. Reading this needs the calendar.acls.readonly scope, which calendar.readonly does not cover: if it was not granted the call says so rather than reporting an empty list, because "could not read" and "shared with nobody" are different answers.

NameTypeReqDescription
calendarstringyesThe calendar id, its title, or "primary" for this account's own calendar.
NameTypeReqDescription
actionstring––
api_requestsintegeryes–
calendar_idstringyes–
changednull|object––
dry_runboolean––
notesnull|array––
notificationstring––
publicbooleanyes–
sharingnull|arrayyes–
sharing_beforenull|array––

No examples provided.

manage_calendar ~613

Change a calendar, or change how you see it, or add and remove it from your list. A calendar is two things and the difference is visible to other people: the CALENDAR itself — its title, description, location and time zone — is what everybody it is shared with sees, and YOUR SUBSCRIPTION to it — the color, the name you give it, whether it is hidden, what you are emailed about — is yours alone. Renaming the calendar renames it for the team; `my_name` renames it only for you. `subscribe` adds an existing calendar to your list by id; `unsubscribe` removes it from YOUR list and does not delete it, does not touch its events and changes nothing for anybody else. Use delete_calendar to remove a calendar itself. `notifications` replaces the whole list of what you are emailed about on this calendar; an empty list turns them all off. Email is the only delivery Google offers. Only the fields you pass are touched. There is no `etag` here on purpose: the two halves are two resources with two etags, so each patch is made under the etag of the read this call just did, and the result shows before and after for every field it changed. `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have.

NameTypeReqDescription
calendarstringyesThe calendar id or title. Ids come from list_calendars.
color_idnull|string–Your color for it, from the calendar palette get_settings reports.
descriptionnull|string–New description. Pass an empty string to clear it.
dry_runboolean–Report what would change, without writing.
hiddennull|boolean–Hide it from your calendar list.
locationnull|string–New location. Pass an empty string to clear it.
my_namenull|string–The name YOU see for this calendar. Nobody else sees it. Pass an empty string to go back to its own title.
notificationsnull|array–What YOU are emailed about on this calendar: creation, change, cancellation, response, agenda. Replaces the whole list; an empty list turns them off.
selectednull|boolean–Whether its events are drawn in the Calendar UI. Not the same as hidden.
subscribeboolean–Add this calendar to your list. It grants no access; it only puts a calendar you can already reach where you can see it.
time_zonenull|string–New IANA time zone for the calendar, such as Europe/Copenhagen.
titlenull|string–New title for the CALENDAR ITSELF, which everybody it is shared with sees. Needs owner access.
unsubscribeboolean–Remove it from YOUR list. It is not deleted, its events stay, and nobody else notices.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarobjectyes–
changesnull|array––
dry_runboolean––
notesnull|array––

No examples provided.

move_event ~628

Move an event to another calendar, which changes who organizes it. The event keeps its id but is addressed on the new calendar from then on. This does NOT change the time — use update_event for that. `scope` is REQUIRED when the event repeats, and there is no default because the same words mean three different things: `instance` changes one occurrence, `series` changes all of them, and `this_and_following` changes this occurrence and every later one. Name the occurrence with the occurrence's own id, or with the series id plus `original_start` — the scheduled start, which list_instances reports, and which still identifies an occurrence somebody has moved. `this_and_following` is not available here: there is nothing to split when the event is simply changing calendars. `notify` is REQUIRED whenever the write can reach another person, and this server has no default in either direction: `none` asks Google to email nobody, `external_only` emails the guests outside your own organization, `all` emails every guest. `none` is refused outright when a guest is outside your organization, because such a guest may have no Google Calendar for the event to appear in and email is then the only way they can learn of it. Whatever you pass, the result says what was ASKED FOR — Google reports nothing about what arrived, and `none` is not a promise of silence. Every write is a patch under If-Match, so it is refused as `[stale]` rather than overwriting somebody who changed this first. Pass `etag` from the get_event you decided on to be held to that exact version; pass `force: true` only when you genuinely mean "whatever it says now". Without `etag`, a write refused that way is read again and made once more if nothing it changes, reaches or asked about has changed, and the result says so. `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have.

NameTypeReqDescription
calendarstringyesThe calendar the event is on now.
dry_runboolean–Report what would move and who would be emailed, without writing.
etagstring–The etag from the get_event you decided on. The move is refused as stale if it moved since.
event_idstringyesThe event id.
forceboolean–Move with If-Match: * rather than being refused if somebody changed it first.
notifystring–Who Google is asked to email: none, external_only or all. Required when the event has guests.
original_startstring–The occurrence's SCHEDULED start, when moving one occurrence of a series.
scopestring–Required when the event repeats: instance or series.
time_zonestring–IANA zone to show the times in.
to_calendarstringyesThe calendar id or title to move it to. Required.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarstringyes–
changesnull|array––
dry_runboolean––
etagstring––
eventnull|object––
notesnull|array––
notificationstringyes–
scopestring––
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

respond_to_event ~552

Answer an invitation: accepted, declined or tentative, with an optional comment. This changes only THIS account's response and nothing else on the event — which is why it is a separate tool rather than an update. Do not RSVP by patching the guest list; that overwrites everybody else's answer. `scope` is REQUIRED when the event repeats, and there is no default because the same words mean three different things: `instance` changes one occurrence, `series` changes all of them, and `this_and_following` changes this occurrence and every later one. Name the occurrence with the occurrence's own id, or with the series id plus `original_start` — the scheduled start, which list_instances reports, and which still identifies an occurrence somebody has moved. `this_and_following` is not available here: answering some occurrences and not others would mean rewriting somebody else's series. `notify` is REQUIRED whenever the write can reach another person, and this server has no default in either direction: `none` asks Google to email nobody, `external_only` emails the guests outside your own organization, `all` emails every guest. `none` is refused outright when a guest is outside your organization, because such a guest may have no Google Calendar for the event to appear in and email is then the only way they can learn of it. Whatever you pass, the result says what was ASKED FOR — Google reports nothing about what arrived, and `none` is not a promise of silence. `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have.

NameTypeReqDescription
calendarstringyesThe calendar the invitation is on.
commentstring–A note that goes alongside the answer.
dry_runboolean–Report what would change and who would be emailed, without writing.
etagstring–The etag from the get_event you decided on.
event_idstringyesThe event id, or the series id when original_start names the occurrence.
forceboolean–Answer with If-Match: * rather than being refused if somebody changed it first.
notifystring–Who Google is asked to email: none, external_only or all. Required when the event has guests.
original_startstring–The occurrence's SCHEDULED start, when answering for one occurrence.
responsestringyesaccepted, declined or tentative. Required.
scopestring–Required when the event repeats: instance or series.
time_zonestring–IANA zone to show the times in.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarstringyes–
changesnull|array––
dry_runboolean––
etagstring––
eventnull|object––
notesnull|array––
notificationstringyes–
scopestring––
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

search_events ~458

Find events matching free text in a window. `from` and `to` are required and take either a yyyy-mm-dd date or an RFC3339 timestamp. A bare date means that whole day in the resolved zone, so from and to on the same date is that one day. Resolve relative expressions like "next Tuesday" yourself before calling: this server does not guess, and the result always echoes the absolute window and the zone it used so you can check the resolution. Google documents the fields the text is matched against: the title, description and location, the guests' and organizer's names and addresses, and a working location's labels; words such as "Out of office" also match those kinds of event, in any language. There is no field syntax: you cannot search "attendee:someone" or restrict it to titles. How words are matched is not documented, and an event you can see only as busy has nothing to match, so treat an empty result as "this search found nothing", not as "there is no such event", and fall back to list_events over the window when you need certainty. event_types narrows the search to some kinds of event, as on list_events. Searching several calendars costs one request each.

NameTypeReqDescription
calendarsnull|array–Calendar ids or titles. Defaults to the primary calendar.
event_typesnull|array–Only events of these types: default, birthday, focusTime, fromGmail, outOfOffice, workingLocation. Leave it out for every type.
fromstringyesStart of the window: yyyy-mm-dd or RFC3339. Required.
max_eventsinteger–Cap on events returned.
page_tokenstring–Continue a truncated search, from next_page_token, with the same arguments; a token is refused under another query.
querystringyesFree text, matched against the title, description, location, and the guests' and organizer's names and addresses. There is no field syntax.
time_zonestring–IANA zone to read the window and show the times in.
tostringyesEnd of the window: yyyy-mm-dd or RFC3339. Required.
NameTypeReqDescription
api_requestsintegeryes–
calendarsnull|arrayyes–
event_typesnull|array––
eventsnull|arrayyes–
ical_uidstring––
matchedintegeryes–
next_page_tokenstring––
recurring_expandedbooleanyes–
shownintegeryes–
time_zonestringyes–
time_zone_sourcestringyes–
truncatedbooleanyes–
windowobjectyes–

No examples provided.

share_calendar ~587

Give somebody access to a calendar, or change the access they already have. `who` is an email address, a group address, a domain, or "anyone" for the public internet. An address is read as one person unless this calendar already has a rule for it — pass `scope_type` to be sure, because a group address and a person's look identical. `role` is what they may do: freeBusyReader, reader, writerWithoutPrivateAccess, writer or owner. The result explains the one it set. Sharing with "anyone" publishes the calendar to the whole internet and needs `allow_public: true`: removing the rule later stops new readers and takes nothing back from whoever already looked. `notify` is REQUIRED and has no default: `all` asks Google to email about the change, `none` asks it not to. Google's own default here is to EMAIL — the opposite of its default on an event — which is why this server asks rather than inheriting either. `external_only` has no meaning on a sharing change and is refused: Google's switch is on or off, with no internal/external split. Whatever you pass, the result says what was ASKED FOR; the API reports nothing about what arrived. The result lists who could see the calendar before and who can see it now, because "shared with somebody" is not an answer to "who can see this". `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have. When the client can, the server also asks the person before a share that publishes the calendar, opens it to a whole domain, or makes somebody an owner; a call they do not confirm is [blocked], and is not made again unless they ask.

NameTypeReqDescription
allow_publicboolean–Required to share with "anyone", which publishes the calendar to the whole internet.
calendarstringyesThe calendar to share. You must own it.
dry_runboolean–Report what access would change and who would be emailed, without writing.
notifystring–Whether Google emails about the change: all or none. Required; there is no default, and Google's own is to email.
rolestringyesWhat they may do: freeBusyReader, reader, writerWithoutPrivateAccess, writer or owner. Required.
scope_typestring–user, group, domain or default. Optional: an address is read as one person unless a rule for it already exists.
whostringyesAn email address, a group address, a domain, or "anyone" for the public internet. An address may be a mailbox such as "Sample Person" <person@example.com>; only the address is used. Required.
NameTypeReqDescription
actionstring––
api_requestsintegeryes–
calendar_idstringyes–
changednull|object––
dry_runboolean––
notesnull|array––
notificationstring––
publicbooleanyes–
sharingnull|arrayyes–
sharing_beforenull|array––

No examples provided.

unshare_calendar ~284

Take somebody's access to a calendar away. `who` is the address, domain or "anyone" whose rule should go; the server finds the rule itself, and says so if there is none. There is no notify here, and that is Google's shape rather than an omission: nobody is emailed when access is removed and there is no way to ask for it. They are not told — they find the calendar gone. Removing the public rule stops new readers and takes nothing back from anybody who already looked. The result lists who could see the calendar before and who can see it now, because "shared with somebody" is not an answer to "who can see this". `dry_run: true` reports exactly what would change and how many guests would be emailed, without writing anything. Use it when you are not certain which event or which occurrence you have.

NameTypeReqDescription
calendarstringyesThe calendar to stop sharing. You must own it.
dry_runboolean–Report whose access would go, without writing.
scope_typestring–user, group, domain or default, when the address alone is ambiguous.
whostringyesThe address, domain, or "anyone", whose access should go. An address may be a mailbox such as "Sample Person" <person@example.com>; only the address is used. Required.
NameTypeReqDescription
actionstring––
api_requestsintegeryes–
calendar_idstringyes–
changednull|object––
dry_runboolean––
notesnull|array––
notificationstring––
publicbooleanyes–
sharingnull|arrayyes–
sharing_beforenull|array––

No examples provided.

update_event ~1,755

Change an event. Only the fields you pass are touched; everything else is left exactly as it is, so this can never drop a guest list or flatten a series the way a whole-resource write does. Guests are added and removed one at a time with `add_guests` and `remove_guests`, optional guests added with `add_optional_guests`, and rooms booked with `add_rooms`, applied to the list as it is read, so somebody else's RSVP arriving in between is reported rather than overwritten. An address already on the event keeps the role it has, and the result names it: this server does not make a guest optional or required, and a call that would add nothing else is refused as having nothing to change. An address may be bare or a mailbox such as "Sample Person" <person@example.com>, the way a mail server hands one over; only the address is used, and one entry holds one address. `scope` is REQUIRED when the event repeats, and there is no default because the same words mean three different things: `instance` changes one occurrence, `series` changes all of them, and `this_and_following` changes this occurrence and every later one. Name the occurrence with the occurrence's own id, or with the series id plus `original_start` — the scheduled start, which list_instances reports, and which still identifies an occurrence somebody has moved. `this_and_following` is two calls: the original series is ended before this occurrence and a NEW series starts at it with a new id, and any exception after this occurrence is reset. The result says so. `popup_reminders` and `email_reminders` are minutes before the start, 0 to 40320, at most five in all. Either one replaces the whole set, so pass both to keep both kinds, and an empty list given alone means no reminders. `default_reminders: true` goes back to the calendar's own. Reminders are yours alone: Google keeps them per person, so they never notify a guest. A write that changes only reminders needs no `notify`, except with `this_and_following`, whose new s…

NameTypeReqDescription
add_conferenceboolean–Ask Google for a Google Meet link. Refused when the event already has a conference.
add_guestsnull|array–Email addresses to invite, added to the guests already there.
add_optional_guestsnull|array–Email addresses to invite as optional guests, added to the guests already there. An address already on the event keeps the role it has, and the result says so. A room cannot be optional.
add_roomsnull|array–Addresses of rooms or other resources to book. A room is not a guest; an address here that is not a room's still counts as one.
calendarstringyesThe calendar the event is on. An event id is unique per calendar, not globally.
default_remindersboolean–Go back to the calendar's own reminders.
descriptionnull|string–New description. Omit to leave it; pass an empty string to clear it.
dry_runboolean–Report what would change and who would be emailed, without writing.
email_remindersnull|array–Your email reminders, in minutes before the start, 0 to 40320. At most five reminders in all.
endstring–New end. For an all-day event this is the last day, included.
etagstring–The etag from the get_event you decided on. The write is refused as stale if it moved since.
event_idstringyesThe event id, or the series id when original_start names the occurrence.
forceboolean–Write with If-Match: * — overwrite whatever it says now, rather than being refused if somebody changed it.
free_not_busynull|boolean–Mark the time free rather than busy.
guests_can_invite_othersnull|boolean–Whether guests may invite others.
guests_can_modifynull|boolean–Whether guests may change the event.
guests_can_see_other_guestsnull|boolean–Whether guests see the guest list.
locationnull|string–New location. Omit to leave it; pass an empty string to clear it.
notifystring–Who Google is asked to email: none, external_only or all. Required when the event has guests or the call adds one.
original_startstring–The occurrence's SCHEDULED start, from list_instances. Use it with the series id to name one occurrence.
popup_remindersnull|array–Your popup reminders, in minutes before the start, 0 to 40320. Replaces all your reminders on the event; an empty list given alone removes them.
recurrencenull|array–New RFC 5545 lines. An empty list stops the event repeating.
remove_guestsnull|array–Email addresses to uninvite, rooms included.
scopestring–Required when the event repeats: instance, series or this_and_following.
startstring–New start: yyyy-mm-dd or RFC3339, matching what the event already is.
time_zonestring–IANA zone the new times are written in.
titlenull|string–New title. Omit to leave it; pass an empty string to clear it.
visibilitynull|string–default, public or private. On one occurrence a less restrictive value is refused, because Google ignores it.
NameTypeReqDescription
actionstringyes–
api_requestsintegeryes–
beforenull|object––
calendarstringyes–
changesnull|array––
dry_runboolean––
etagstring––
eventnull|object––
notesnull|array––
notificationstringyes–
scopestring––
time_zonestringyes–
time_zone_sourcestringyes–

No examples provided.

Install

How do I install the io.github.mmedum/google-calendar-mcp server?

io.github.mmedum/google-calendar-mcp ships as an MCPB bundle, a single file you download and open in an MCP host that supports MCPB bundles, such as Claude Desktop. The host reads the launch command from the bundle's own manifest, so there is no command to copy. Before opening it, check the file's SHA-256 matches the one the MCP registry declares for it, e56204b7416e170e54ca17d769e78f58821b362b5def9ebcd7efc178873cc564; the commands to do that are on this page. If it does not match, do not open it.

mcpb · google-calendar-mcp_3.1.0.mcpb

Download bundle

Check the download matches the SHA-256 the MCP registry declares before you open it. If it does not match, do not open the file.

SHA-256

e56204b7416e170e54ca17d769e78f58821b362b5def9ebcd7efc178873cc564

macOS / Linux

echo "e56204b7416e170e54ca17d769e78f58821b362b5def9ebcd7efc178873cc564  google-calendar-mcp_3.1.0.mcpb" | shasum -a 256 -c

Windows (PowerShell)

(Get-FileHash -Algorithm SHA256 .\google-calendar-mcp_3.1.0.mcpb).Hash -eq "e56204b7416e170e54ca17d769e78f58821b362b5def9ebcd7efc178873cc564"

Run it in the folder you saved the bundle to, then open the file with an MCPB-capable host such as Claude Desktop.

Common questions

What is the io.github.mmedum/google-calendar-mcp server?

io.github.mmedum/google-calendar-mcp is listed in the public MCP registry as io.github.mmedum/google-calendar-mcp. Google Calendar over MCP: calendars, events, recurrence and availability. This page covers its MCPB bundle (https://github.com/mmedum/google-calendar-mcp/releases/download/v3.1.0/google-calendar-mcp_3.1.0.mcpb).

Is the io.github.mmedum/google-calendar-mcp server safe to use?

io.github.mmedum/google-calendar-mcp scores 64 out of 100 on VerifyMCP. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.mmedum/google-calendar-mcp server expose?

io.github.mmedum/google-calendar-mcp exposes 19 tools: cancel_event, check_availability, create_calendar, create_event, get_calendar, and 14 more. Their descriptions and schemas cost roughly 10,262 tokens of context every time the server is loaded.

What licence is the io.github.mmedum/google-calendar-mcp server under?

io.github.mmedum/google-calendar-mcp declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.