Google Calendar MCP
Provides tools for managing Google Calendar across multiple independent Google accounts through a single MCP interface, with per-account OAuth grants and role-based access control. Capabilities include listing calendars, reading events, querying free/busy information, and creating, updating, moving, and deleting events, as well as a built-in personal time-management/planning assistant.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Google Calendar MCPWhat's on my work calendar tomorrow?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
google-calendar-mcp
A multi-account, RBAC-enforced Google Calendar MCP server, with a personal time-management assistant built in.
One MCP interface → an account router → an authorization layer → N independent Google OAuth identities → the Google Calendar API.
Claude
│ (stdio, JSON-RPC)
┌───────▼────────┐
│ MCP Server │ 25 tools, filtered by session role
└───────┬────────┘
┌───────▼────────┐
│ Account Router │ explicit id, or refuse to guess
└───────┬────────┘
┌───────▼────────┐
│ Authorizer │ 4 gates, all must allow
└───────┬────────┘
┌──────────┬──────────┬──┴───────┬──────────┬──────────┐
│ personal │ work │ business │ family │ project │
│ OAuth #1 │ OAuth #2 │ OAuth #3 │ OAuth #4 │ OAuth #5 │
│ viewer │ editor │scheduler │ viewer │ editor │
└────┬─────┴────┬─────┴────┬─────┴────┬─────┴────┬─────┘
└──────────┴──────────┴──────────┴──────────┘
│
Google Calendar API v3Each account has its own OAuth grant, its own encrypted token file, its own role, and its own effective permissions. There is no shared session.
Contents
Related MCP server: Google Calendar MCP Server
Requirements
Node.js 20 or newer (tested on 22)
A Google Cloud project with the Calendar API enabled
One Google account per calendar you want to connect
Quick start
npm install
cp .env.example .env
# Generate the token-vault key and paste it into .env as MCP_MASTER_KEY
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
# Fill in GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET (see Google Cloud setup)
npm run build
npm run auth -- --account personal --role viewer
npm run doctorGoogle Cloud setup
You need one Google Cloud project and one OAuth client. All five accounts authorize against that same client — that is the normal and supported pattern, and Google allows up to 100 refresh tokens per account per client.
1. Create the project
Name it, e.g.
calendar-mcp, and click Create.Make sure it is selected in the project picker at the top.
2. Enable the Calendar API
Go to APIs & Services → Library.
Search for Google Calendar API.
Click Enable.
3. Configure the OAuth consent screen
Go to APIs & Services → OAuth consent screen.
Choose a user type:
External — required for personal
@gmail.comaccounts.Internal — only if every account is in one Google Workspace organisation. This is simpler: no verification, no user cap.
Fill in the app name, your support email, and your developer email.
4. Add the scopes
Add exactly these, and no others:
Scope | Why |
| binds each token to an identity |
| records which Google account a token belongs to |
| list calendars, read events, query free/busy |
| create/update/move/delete events only |
Read-only accounts request only the first three.
Deliberately not requested:
.../auth/calendar. That scope also permits deleting whole calendars and rewriting sharing ACLs. This server never does either, so it never asks for the power to.
calendar.readonly and calendar.events are sensitive scopes. See the
publishing step below for what that means in practice.
5. Create the OAuth client
Go to APIs & Services → Credentials → Create Credentials → OAuth client ID.
Application type: Desktop app. ← this matters
Name it, then click Create.
Copy the client ID and client secret into
.env.
Why Desktop app: for installed apps Google accepts a loopback redirect (
http://127.0.0.1:<port>) on any port, so you do not have to register a fixed redirect URI and the auth flow keeps working if the port is busy. If you pick "Web application" instead, you must addhttp://127.0.0.1:42813/oauth2callbackas an authorized redirect URI and keepMCP_OAUTH_PORTpinned to that exact port.
6. Publish the app — do not skip this
Go to OAuth consent screen → Publishing status → Publish app → "In production".
This is the single most important step for a setup you intend to keep.
Publishing status | Refresh token lifetime |
Testing | expires after 7 days |
In production | does not expire (until revoked or unused for 6 months) |
If you leave the app in Testing, every account silently stops working a week later and you re-authorize all five. Google applies the 7-day cap to any Testing-status External app requesting more than basic profile scopes.
Publishing an unverified app with sensitive scopes has two consequences, both acceptable for personal use:
Each account sees a "Google hasn't verified this app" interstitial once, during consent. Click Advanced → Go to <app name> (unsafe). You are the developer of this app; you are the one it is warning you about.
The project is capped at 100 new users for its lifetime. You are using five.
You only need to submit for verification if you intend to distribute this to other people.
7. Add test users (only while in Testing)
If you keep the app in Testing while experimenting, add each of the five Google addresses under Audience → Test users. Accounts not on that list cannot authorize at all.
Connecting five accounts
Run the command once per account. Each run is an independent OAuth flow and produces an independent token file.
npm run auth -- --account personal --role viewer --access read_only
npm run auth -- --account work --role editor --access read_write
npm run auth -- --account business --role scheduler --access read_write
npm run auth -- --account family --role viewer --access read_only
npm run auth -- --account project --role editor --access read_writeEach run:
starts a loopback listener on 127.0.0.1,
opens Google's consent screen with
prompt=consent select_account,sign in as the account you named — the account chooser is shown every time precisely so the browser's current session is not silently reused,
verifies the returned
id_tokenand records the email,encrypts the tokens to
data/tokens/<id>.token.enc.json,registers the account in
data/accounts.json.
If you sign in as an account that is already connected under a different id, the command stops and tells you — two ids pointing at the same calendars is almost never intended.
Verify everything:
npm run doctorThis refreshes each token against Google, lists the visible calendars, and cross-checks that each account's primary calendar matches its registered email — which is a direct test that no two accounts have crossed tokens.
Useful follow-ups:
npm run accounts -- list
npm run accounts -- show work
npm run accounts -- calendars work
npm run accounts -- role personal viewer
npm run accounts -- set-timezone work Asia/Jakarta
npm run accounts -- disable family
npm run accounts -- remove project # revokes at Google, then deletesConnecting to Claude
Claude Desktop (local stdio) — the supported path
Claude Desktop launches local MCP servers as child processes over stdio. Edit:
Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"google-calendar": {
"command": "node",
"args": ["C:\\Users\\you\\google-calendar-mcp\\dist\\index.js"],
"env": {
"GOOGLE_CLIENT_ID": "xxxx.apps.googleusercontent.com",
"GOOGLE_CLIENT_SECRET": "GOCSPX-xxxx",
"MCP_MASTER_KEY": "your-generated-key",
"MCP_DATA_DIR": "C:\\Users\\you\\google-calendar-mcp\\data",
"MCP_DEFAULT_TIMEZONE": "Asia/Jakarta",
"MCP_PRINCIPAL_ROLE": "admin"
}
}
}
}Use absolute paths, run npm run build first, and restart Claude Desktop
completely. Values in env win over .env, by design.
Claude Code
claude mcp add google-calendar -- node /absolute/path/to/dist/index.jsOr add the same JSON block to .mcp.json in your project.
Claude web / mobile (custom connectors) — what does not work
claude.ai connects to remote MCP servers over HTTP with OAuth. It cannot launch a process on your machine, so this server — a local stdio process reading an encrypted vault on your disk — is not reachable from the web or mobile apps as written.
Your options, honestly stated:
Option | Trade-off |
Use Claude Desktop or Claude Code | Works today. Recommended. |
Proxy via | Bridges stdio to HTTP, but you must expose and secure that endpoint yourself. |
Port to Streamable HTTP and host it | Real work: you would add MCP's OAuth authorization-server flow, per-user token isolation, and a trusted host. The RBAC layer here is transport-agnostic and would carry over unchanged; |
Do not expose this server over HTTP without adding authentication. As written it trusts its caller completely, which is correct for a local stdio process owned by one user and wrong for anything reachable over a network.
Planning assistant
Beyond reading and writing calendars, the server plans your week: it reads every connected calendar, fits a routine around the real commitments, and writes nothing until you approve.
Four workflows, as MCP prompts
Prompt | What it does |
| Review the week just gone, propose the week ahead, apply on approval |
| One day, planned around what is already booked |
| Short morning briefing: what is fixed, what clashes, best focus block |
| Find realistic slots for a specific commitment |
These are prompts rather than tools because a weekly planning session is something you start, not something the model decides to do. They carry the operating rules, so the behaviour survives a fresh conversation.
The routine model
data/routine.json describes the week in three kinds of commitment:
anchor - a fixed window that structures the day (the main job). May be porous: a work-from-anywhere block reserves 10:00-19:00 but commits only 7h of it, leaving genuine gaps that lunch, dinner and English practice reuse. That is what stops the planner blanking out nine hours it has no business blanking out.
fixture - short daily invariants: morning routine, meals, wind-down.
flexible - a duration that must land somewhere sensible. The planner chooses when, by score.
Each activity declares an energy kind, and that drives placement against a focus curve anchored to your wake time:
Energy | Placed where | Example |
| 1-2.5h after waking | jogging |
| peak analytical window, 1.5-4h after waking | DSA study |
| anywhere with decent energy | part-time work, English |
| position matters, focus does not | meals, wind-down |
Rules the engine enforces
These are code, not prompt text, so they hold every time:
Sleep is carved out first; the day is what remains.
Real calendar events outrank everything in the routine.
Exercise stays in the morning.
DSA lands at peak focus before work, never straight after a long block.
Nothing is placed within 90 minutes after a draining activity.
Part-time work is never placed inside the main job window.
Meals and English may borrow porous WFA gaps, capped at the anchor's spare capacity.
A break inside the work block counts as a real break.
Recurring activities keep the same clock time all week. A predictable routine beats a marginally better one that moves.
Propose, approve, apply
propose_schedule reads calendars, computes a plan, writes nothing -> plan_id
Claude shows you the week and the workload verdict
apply_schedule returns a confirm_token and an exact summary
you approve
apply_schedule with the token -> events createdThe gate is structural, not advisory:
propose_scheduleholds no write permission, so it cannot write.Plans expire after an hour; the calendars will have moved on.
A plan applies once.
Busy time is re-read immediately before writing, so a meeting booked between proposal and approval makes that block skip, not double-book.
The nine-hour main job block is never written. It describes an obligation you already have, and writing it would bury the calendar it is meant to clarify.
It tells you when the week does not fit
A 9-hour main job plus 3 hours of part-time plus study and exercise comes to roughly 15h45m of scheduled time per weekday. The planner produces the best arrangement it can and then says so plainly:
verdict: heavy
scheduled: 85.5h productive: 74.3h average sleep: 7h
[warning] Monday is scheduled for 15h 45m, over your 12h ceiling.
[warning] Monday has 5h of demanding work with no break in it.Sessions that could not be placed are reported as shortfalls, never dropped quietly. A sleep breach is an error, not a warning: everything else in the plan is paid for out of sleep.
A typical weekday it produces:
05:45 wake
05:45 Morning routine
06:30 Jogging / exercise
07:30 Breakfast
08:15 DSA / competitive programming <- peak focus, before work
10:00 Main job (WFA)
12:30 Lunch <- inside the WFA gap
15:15 English speaking practice <- inside the WFA gap
18:15 Dinner <- inside the WFA gap
19:15 Part-time remote work
22:15 Wind down
22:45 sleepTuning it
In conversation: "make DSA 60 minutes", "I want to wake at 6", "drop
English to twice a week" - these map to update_routine and persist.
reset_routine restores the default. data/routine.json is plain JSON and
safe to edit by hand; invalid values are rejected at startup with the offending
activity named.
Roles and permissions
Permission vocabulary
calendar.read calendar.create account.list permission.read
calendar.search calendar.update account.connect permission.manage
calendar.freebusy calendar.reschedule account.disconnect system.configure
calendar.delete account.configureRole → permissions
Permission | viewer | editor | scheduler | admin |
| ✅ | ✅ | ✅ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ❌ | ✅ | ✅ | ✅ |
| ❌ | ✅ | ✅ | ✅ |
| ❌ | ✅ | ✅ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ❌ | ❌ | ✅ | ✅ |
| ✅ | ✅ | ✅ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
admin holds the * wildcard. Deletion is admin-only, which is what makes
"work = editor" correctly resolve to delete = denied.
editor and scheduler hold identical calendar permissions. They differ in
the routine: scheduler can tune it, editor cannot, because shaping the week
is scheduling work rather than event editing.
Planning is read-only, so even a viewer session can ask "what would a good
week look like?" - applying that plan needs calendar.create on a real account.
Role → accounts → actions
With the recommended layout:
Account | Role | read | search | free/busy | create | update | delete |
personal | viewer | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
work | editor | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
business | scheduler | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
family | viewer | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
project | editor | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
The deployed account layout
Account id | Purpose | Role | Can create/update | Can delete |
| Primary personal calendar |
| yes | yes |
| Secondary personal calendar |
| no | no |
| Full-time job |
| yes | no |
| Part-time job |
| yes | no |
An account id is a slot, and each slot binds to exactly one Google address; connecting the same address under a second id is refused.
Role beats configuration.
personal2holds read/write OAuth scopes but theviewerrole, and its effective permission is read-only. Widening the OAuth grant, or editingaccounts.json, cannot grant a capability the role does not carry. Tool hiding is a convenience; the server-side check is the source of truth.
Two levels of role
MCP_PRINCIPAL_ROLE— the role the session runs as. A ceiling over everything. Set it toviewerand the whole server is read-only regardless of account roles.Each account's
role— a ceiling for that account.
An action is permitted only if both allow it. Setting the session to viewer
is the simplest way to run a strictly read-only setup.
Security model
Four gates, all must allow
Every privileged call passes through Authorizer.check. There is no second path.
Session role — does
MCP_PRINCIPAL_ROLEgrant this permission at all?Account role — does this account's role grant it?
Account overrides —
deniedPermissionswins over everything, including admin and the wildcard.Granted OAuth scopes — did Google actually grant write access?
Gate 4 is what makes the model hold under a tampered config. Gates 1–3 read from
local files a user could edit. If someone promotes a read-only account to
admin in accounts.json, writes still fail: the stored token physically
cannot write, and the server checks that before calling Google.
Token handling
Encryption at rest. AES-256-GCM, key derived per file with scrypt (N=2¹⁵) from
MCP_MASTER_KEY. Every file has its own random salt and IV.One file per account.
data/tokens/<id>.token.enc.json. No shared token file that a bug could cross-wire.Bound identity. Each encrypted record embeds its account id. Reading
personal's file and findingworkinside is a hard failure, not a warning. This is tested directly.Atomic, serialised writes. Write temp → fsync → rename, with a per-account promise chain. Concurrent refreshes cannot interleave and truncate.
Never exposed. No tool returns a token, a refresh token or the client secret. Integration tests assert this over the actual tool output.
Redacted logs. The logger strips secrets by key name and by value shape (
ya29.…,1//…,GOCSPX-…, JWTs), so a token cannot reach a log file even under an innocuous key.stderr only. stdout belongs to the JSON-RPC stream;
console.logis reassigned to stderr at startup.
Account isolation
One
OAuth2Clientper account id, never shared.A client is loaded only from its own vault file.
The refresh listener captures the account id in its closure, so a refreshed token is always written back to the file it came from.
npm run doctorcross-checks each account's primary calendar id against its registered email — a live test that no two accounts are crossed.
Input validation
Every tool schema is strict: an unknown key is rejected rather than
silently dropped. This matters more than it sounds. A loose schema would
discard a misspelled acount: "work", leaving account undefined, and the
request would fall through to account inference — potentially writing to a
different calendar than the one named. Strict schemas turn that into an
immediate, visible error.
Concurrency
Token vault writes are serialised per account and atomic (write, fsync, rename), so simultaneous refreshes cannot interleave or truncate.
A schedule plan is claimed synchronously before the first
await, so two concurrentapply_schedulecalls cannot both reach the write loop. The loser is told the plan is already being applied.A failed apply releases its claim, leaving the plan usable for a retry.
apply_schedulerefuses to write at all if any calendar could not be re-read first: booking over events the server cannot see is worse than not booking.
Destructive actions
delete_event and disconnect_account require two calls.
The first returns CONFIRMATION_REQUIRED with a plain-language description of
exactly what would happen and a confirm_token. The token is bound to a SHA-256
fingerprint of action + account + calendar + event, is single-use, and expires
(default 5 minutes).
A token minted for "delete X from business" is cryptographically useless against "delete X from personal" — and a mismatch burns the token rather than just rejecting it.
Why at the server layer: MCP's destructiveHint annotation is advisory, and
elicitation is optional in the protocol. Safety that depends on the client
implementing a prompt is not safety. The server enforces its own gate, and the
annotations are sent as well so good clients can also prompt.
Threat model — what this does not defend against
Being explicit about the boundary:
A local attacker with your
MCP_MASTER_KEYand the data directory can decrypt the vault. The key lives in your environment or.env; encryption protects the files at rest (backups, sync folders, stolen disks), not against code running as you.A malicious MCP client. The server trusts its stdio peer. That is correct for a local process you launched and wrong for a network service.
Prompt injection reaching Claude. An event description saying "delete everything" cannot escalate privileges — RBAC and confirmation are enforced server-side — but Claude may still relay hostile text to you. The permission model bounds the blast radius; it does not make event content trustworthy.
Tools
25 tools and 4 prompts. Which tools are advertised depends on
MCP_PRINCIPAL_ROLE; all are enforced server-side regardless.
Read (viewer and above)
Tool | Purpose |
| every account with role, state and effective permissions |
| one account in detail, including granted OAuth access |
| the role model, and why something was denied |
| calendars across accounts, with Google access roles |
| events in a range; fans out across accounts by default |
| unified cross-account timeline, sorted |
| full-text search across accounts |
| one event (account required — ids are account-scoped) |
| busy periods plus a merged timeline |
| overlapping events across accounts |
| free slots across every checked calendar |
Write (editor / scheduler and above)
Tool | Notes |
| routes to one account; |
| patch semantics; time changes also need |
| between calendars within one account (Google cannot move across accounts) |
Planning
Tool | Notes |
| Sleep, work hours, every recurring activity |
| Computes a plan; writes nothing; returns a |
| Creates the events, two-phase confirmed |
| Hours per category, busiest/lightest day, long stretches |
| Change sleep, limits or one activity (scheduler/admin) |
| Restore the defaults (scheduler/admin) |
Admin
Tool | Notes |
| destructive; two-phase confirmation |
| returns the command for the user to run; consent happens in their browser |
| destructive; revokes at Google then deletes locally |
| warns if the role exceeds the granted OAuth scopes |
| pause an account without deleting its tokens |
Deliberately not implemented
OAuth-in-a-tool. A browser consent flow cannot be driven from inside a stdio tool call.
connect_accountreturns the exact command instead.delete_calendar/ ACL editing. Out of scope, and the reason the broadcalendarscope is never requested.Cross-account move. Google has no such operation. Create on the target and delete the original — two explicitly authorized steps.
Example prompts
"Show me all my calendars."
list_calendars→ every calendar on all five accounts, labelled by account.
"What do I have tomorrow?"
list_all_events→ one timeline across all five, each event tagged with its account and email.
"Find conflicts across my work and personal calendars."
find_cross_account_conflictswithaccounts: ["work","personal"]→Doctor Appointment 09:00-10:00 personal Team Meeting 09:30-10:30 work → 30 minutes of overlap
"Find a 60-minute slot next Tuesday when I'm free across all my calendars."
find_available_slots→ merges busy periods from all five, returns slots, and reportschecked_accountsso you can see nothing was missed.
"Create this event on my work calendar."
create_eventwithaccount: "work"→ created; the response saysaccount_resolution: "explicit".
"Create a meeting tomorrow at 10am." (no calendar named)
create_eventwith no account →AMBIGUOUS_ACCOUNT, listing["business","project","work"]. Claude asks which one. Nothing is written.
"Delete the event from my business calendar." First call →
CONFIRMATION_REQUIRED:delete "Board meeting" (Mon, 21 Sep 2026, 09:00) from calendar "Primary" on account "business" (business@example.com)Claude shows that, you approve, second call deletes it.
RBAC in action
"Add a dentist appointment to my personal calendar."
{ "error": { "code": "PERMISSION_DENIED", "message": "Permission \"calendar.create\" is denied on account \"personal\": account \"personal\" has role \"viewer\", which does not grant \"calendar.create\"" } }Claude explains the limit instead of retrying, and instead of writing elsewhere.
"Delete that meeting from work." Denied:
workiseditor, and deletion is admin-only.
"Why can't you delete that?"
describe_permissions→ the full role table and this session's role.
Testing
npm test # 195 tests
npm run test:watch
npm run typecheck
npm run doctor # live check against GoogleSuite | Covers |
| role expansion, the four gates, the account matrix |
| per-account vaults, crossed-token detection, traversal, concurrency |
| ambiguity refusal, explicit routing, no fallback |
| token binding, replay across accounts, expiry, single use |
| interval algebra, conflicts, slots, DST, |
| client binding, refresh persistence, crypto, redaction |
| visibility per role, annotation correctness |
| placement rules, consistency, WFA gaps, overload honesty |
| real handlers end-to-end with a fake Google layer |
| propose/approve/apply gate, re-check before writing |
Expected output:
Test Files 10 passed (10)
Tests 195 passed (195)Representative assertions:
viewer cannot create / update / delete →
PERMISSION_DENIEDeditor can create and update, cannot delete
scheduler can schedule; admin can manage accounts
personaltoken →personalvault only; a swapped file is rejecteda confirm token from
businesscannot delete onworkan unqualified write with 3 eligible accounts →
AMBIGUOUS_ACCOUNT, nothing written
The integration tests run the real authorizer, router and confirmation guard. Only Google's HTTP layer is replaced, so an RBAC regression fails there too.
Troubleshooting
invalid_grant / tokens die every 7 days
Your OAuth consent screen is still in Testing. Set publishing status to In production (see step 6), then re-authorize each account. This is the most common failure with this kind of setup.
"Google hasn't verified this app"
Expected for an unverified app using sensitive scopes. Advanced → Go to <app> (unsafe). To remove it entirely you would need Google verification.
Access blocked: <app> has not completed the Google verification process
The account is not on the test-user list while the app is in Testing. Either add it under Audience → Test users, or publish to production.
Google did not return a refresh token
The account previously authorized this client. Remove the app at https://myaccount.google.com/permissions for that account, then re-run.
VAULT_LOCKED / "Could not decrypt the token vault"
MCP_MASTER_KEY differs from the value used at authorization time. Restore the
original key, or delete data/tokens/ and re-authorize.
Claude Desktop shows no tools
npm run build— the config points atdist/, notsrc/.Use absolute paths in
claude_desktop_config.json.Restart Claude Desktop fully.
Check
MCP_PRINCIPAL_ROLE:viewerlegitimately hides every write tool.Run the server manually — it prints startup errors to stderr:
node dist/index.jsClaude Desktop logs:
%APPDATA%\Claude\logs\(Windows),~/Library/Logs/Claude/(macOS).
The server starts then immediately disconnects
Something wrote to stdout and corrupted the JSON-RPC stream. This server
reassigns console.log to stderr at startup; if you add code, never print to
stdout.
AMBIGUOUS_ACCOUNT on every write
Working as designed: several accounts can take the write. Name one
(account: "work"), or narrow the roles so only one account is eligible.
PERMISSION_DENIED when the role looks right
Run npm run doctor. The usual cause is a role/scope mismatch — the account was
authorized read_only but assigned a writing role. Fix:
npm run auth -- --account work --role editor --access read_writeCALENDAR_NOT_FOUND for a calendar you can see
The account's includeCalendars / excludeCalendars policy hides it. Check
npm run accounts -- show <id>.
Rate limits
GOOGLE_RATE_LIMITED is retried with exponential backoff and jitter. Persistent
limits mean too many calendars or too wide a range — narrow the request.
Configuration reference
Variable | Required | Default | Meaning |
| ✅ | — | OAuth client id |
| ✅ | — | OAuth client secret |
| ✅ | — | token-vault encryption passphrase |
|
| session role ceiling | |
| host zone | IANA zone, e.g. | |
|
| registry and vault location | |
|
| loopback port for | |
|
| hide tools the session role cannot use | |
|
| confirm-token lifetime | |
|
| how long a proposed schedule stays applicable | |
|
|
|
Data layout
data/
├── accounts.json # roles, labels, calendar policy — no secrets
├── routine.json # sleep, work hours, activities — no secrets
└── tokens/
├── personal.token.enc.json # AES-256-GCM, unique salt + IV
├── work.token.enc.json
├── business.token.enc.json
├── family.token.enc.json
└── project.token.enc.jsonBack up data/ and MCP_MASTER_KEY together — neither is useful alone.
data/ is gitignored.
Per-account options in accounts.json
{
"id": "work",
"role": "editor",
"enabled": true,
"defaultCalendarId": "primary",
"timezone": "Asia/Jakarta", // overrides the server default
"includeCalendars": ["primary"], // allow-list
"excludeCalendars": ["holidays@..."], // always wins
"deniedPermissions": ["calendar.delete"], // beats any role, including admin
"extraPermissions": [] // widen without changing the role
}Project layout
src/
├── index.ts stdio entry; stdout protection
├── server.ts tool registration and role filtering
├── context.ts dependency wiring
├── config.ts environment configuration
├── errors.ts typed, secret-free error model
├── confirm.ts two-phase destructive-action guard
├── rbac/
│ ├── permissions.ts the vocabulary
│ ├── roles.ts role → permissions
│ └── authorization.ts the four gates ← Google-agnostic
├── auth/
│ ├── crypto.ts AES-256-GCM + scrypt
│ ├── token-store.ts per-account encrypted vault
│ ├── oauth.ts PKCE loopback flow
│ ├── scopes.ts minimum-scope selection
│ └── account-manager.ts per-account client binding and refresh
├── accounts/
│ ├── registry.ts accounts.json
│ └── routing.ts explicit routing; refuses to guess
├── google/
│ ├── calendar-client.ts error translation and retry
│ └── calendar-service.ts calendar operations, per account
├── scheduling/
│ ├── intervals.ts merge, invert, conflict sweep
│ └── slots.ts availability search
├── planner/
│ ├── routine.ts the routine profile and its store
│ ├── energy.ts focus curve, anchored to wake time
│ ├── planner.ts the scheduling engine (deterministic)
│ ├── workload.ts overload detection, honest verdicts
│ └── plan-store.ts proposals held between propose and apply
├── prompts.ts plan_week, plan_tomorrow, daily_check_in, find_time_for
├── tools/ MCP tool definitions
├── util/ logger, time, env
└── cli/ auth, accounts, doctorrbac/ imports nothing from google/. The authorization layer is reusable for
any resource, and is tested without a network.
Sources
Using OAuth 2.0 to access Google APIs — refresh-token expiry and per-client limits
Unverified apps · When verification is not needed · Sensitive scope verification
Prior art reviewed: nspady/google-calendar-mcp — multi-account, but auto-selects the highest-permission account for writes and has no role model. This server refuses to guess instead.
Licence
MIT
Available Tools
25 toolsapply_scheduleApply an approved scheduleA
Create calendar events for a plan the user has approved. Requires a plan_id from propose_schedule. The first call returns a confirm_token and a summary of exactly what will be created; call again with the token only after the user has said yes. Busy time is re-checked immediately before writing, so anything that became busy since the proposal is skipped rather than double-booked.
| Name | Required | Description | Default |
|---|---|---|---|
| account | No | Account to create the events on. Required when more than one account is eligible. | |
| plan_id | Yes | The plan_id returned by propose_schedule. | |
| calendar | No | Calendar id on that account. Defaults to its default calendar. | |
| confirm_token | No | Confirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described. | |
| skip_activities | No | Activity ids the user declined, e.g. ["part-time"]. Everything else is created. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the two-phase CONFIRMATION_REQUIRED flow, the re-check of busy time immediately before writing, and the fact that newly-busy slots are skipped rather than double-booked. This is precisely the behavioral context an agent cannot infer from readOnlyHint/destructiveHint flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the purpose and followed by the guardrail flow and the safety behavior. No filler and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by describing what the first call returns (confirm_token plus a summary), and it fully explains the write-time safety behavior. Nothing an agent needs in order to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning about the confirm_token sequencing and about skip_activities by explaining that busy time is re-checked so declined/conflicting activities are dropped. That is workflow semantics beyond the per-field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create calendar events for a plan') and distinguishes itself from the sibling propose_schedule by describing the apply step versus the proposal step. An agent can tell it apart from create_event and propose_schedule without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the prerequisite (plan_id from propose_schedule) and the exact two-call sequence, including the condition that the token is supplied only after the user approves. It stops short of naming when to prefer this over raw create_event, but the workflow routing is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_freebusyCheck free/busyARead-onlyIdempotent
Return the busy periods across accounts in a time range, plus the merged busy timeline. Use this to answer "am I free at 3pm?" without reading event details.
| Name | Required | Description | Default |
|---|---|---|---|
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| time_max | Yes | End of the range, ISO 8601. | |
| time_min | Yes | Start of the range, ISO 8601. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| calendars | No | Restrict to these calendar ids. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so safety is covered. The description adds real behavioral value by disclosing the shape of the result — per-account busy periods plus a merged timeline — and the cross-account aggregation, which is meaningful given there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, and the return contract is front-loaded before the usage hint. Every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an aggregated free/busy query with no output schema, the description supplies enough about what comes back to call it correctly, and parameters are fully covered by the schema. It stops short of explaining merging semantics across timezones or how empty/overlapping periods are represented, which would matter for an aggregation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and all five parameters (accounts, time_min, time_max, timezone, calendars) are documented in the schema itself, including the default-permission semantics for accounts. The description only restates the time-range notion, adding no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Return the busy periods across accounts ... plus the merged busy timeline') with clear scope. It implicitly separates itself from detail-reading siblings via 'without reading event details,' but it never distinguishes itself from the very close sibling find_available_slots, which occupies nearly the same conceptual space.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete usage context ('Use this to answer "am I free at 3pm?"') and an implied when-not ('without reading event details'), which steers the agent away from list_events/get_event. It does not, however, address when to prefer find_available_slots or find_cross_account_conflicts, both obvious adjacent tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connect_accountConnect a Google accountA
Return the exact command the user must run to connect a new Google account. OAuth consent happens in the user's browser, not through this tool, so this returns instructions rather than performing the login.
| Name | Required | Description | Default |
|---|---|---|---|
| role | No | Role to assign. Start with the least privilege that meets the need. | viewer |
| access | No | OAuth scopes to request. read_only cannot be escalated later without re-authorizing. | read_only |
| account | Yes | The short id to register, e.g. "work" or "family". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses the key behavioral trait: the tool returns a command string and does not perform the login, with OAuth consent happening out-of-band in the browser. It does not cover what happens if the account id already exists or how the returned command should be conveyed, which the non-idempotent annotation hints matters. No direct contradiction with readOnlyHint=false, since the description never claims the tool is side-effect free.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with what is returned, followed by the crucial caveat about where consent happens. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 3 fully documented parameters and no output schema, the description supplies the one thing the schema cannot: that the return value is an instruction to hand to the user rather than an action performed in-band. Adequate for the tool's complexity, though edge behavior (duplicate account ids) is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents 'role', 'access', and 'account' with enums and defaults. The description mentions none of them, so it adds nothing beyond the structured fields; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Return the exact command the user must run to connect a new Google account') and immediately dispels the wrong mental model that the tool performs the OAuth flow. An agent can distinguish this from disconnect_account or set_account_role without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states the context: OAuth consent happens in the user's browser, so this tool is used to obtain the instructions rather than to log in. It does not explicitly name a sibling alternative (e.g., disconnect_account) or state prerequisites, so it is strong but not fully routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_eventCreate an eventA
Create an event on one account. If account is omitted and more than one account could take the write, this fails with AMBIGUOUS_ACCOUNT - ask the user which calendar to use rather than picking one.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | End time, ISO 8601. | |
| start | Yes | Start time, ISO 8601. Interpreted in `timezone` if it has no offset. | |
| title | Yes | Event title. | |
| account | No | The account id to act on, e.g. "work". If omitted, the server uses the only eligible account, or returns AMBIGUOUS_ACCOUNT so you can ask the user which one to use. Never guess. | |
| all_day | No | Create an all-day event. | |
| calendar | No | Calendar id. Defaults to the account's configured default calendar ("primary" unless changed). | |
| location | No | ||
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| attendees | No | Attendee email addresses. Invitations are only emailed if send_updates is set. | |
| recurrence | No | RRULE strings, e.g. ["RRULE:FREQ=WEEKLY;BYDAY=MO"]. | |
| description | No | ||
| send_updates | No | Who to email about this change. Defaults to "none" - never notify people unless the user asked you to. | |
| reminder_minutes | No | Popup reminder, minutes before start. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds critical behavioral context beyond the annotations: the AMBIGUOUS_ACCOUNT failure mode when `account` is omitted, and the instruction not to guess. Annotations correctly declare a non-destructive, non-idempotent write operation, and the description does not contradict them. However, it omits other useful behaviors — e.g., the default 'none' for send_updates (though that is in the schema) and whether the event is immediately visible or requires confirmation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero waste. The main action is front-loaded, and the failure-mode guidance is directly attached to the condition that triggers it. Every part of the description earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter creation tool with 85% schema coverage and no output schema, the description covers the most agent-critical behavioral nuance: account ambiguity failure. It doesn't mention the return value (event ID) or default notification behavior, but those are largely covered by the schema. The description is complete enough for an agent to call correctly and handle the main error case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 85%, so the schema already documents most parameters (account, send_updates, timezone, recurrence, etc.). The description reinforces the account parameter's fallback behavior but doesn't add syntax or format details for other parameters beyond what the schema provides. Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Create an event') and adds a scope qualifier ('on one account') that distinguishes it from sibling tools like update_event, move_event, or propose_schedule. An agent can tell this is for direct event creation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states the when-not condition — if `account` is omitted and multiple accounts are eligible, it fails with AMBIGUOUS_ACCOUNT and the agent should ask the user rather than guess. It does not explicitly name alternative tools (e.g., update_event, propose_schedule), but the guidance on account selection is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_eventDelete an eventADestructive
Permanently delete an event. Destructive and irreversible. The first call returns CONFIRMATION_REQUIRED with a description of exactly what would be deleted and a confirm_token; show that to the user, and only call again with the token once they have explicitly approved it.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| calendar | No | Calendar id. Defaults to the account's configured default calendar ("primary" unless changed). | |
| event_id | Yes | ||
| send_updates | No | Who to email about this change. Defaults to "none" - never notify people unless the user asked you to. | |
| confirm_token | No | Confirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and readOnlyHint=false, but the description goes well beyond them by disclosing the confirmation handshake, the exact return of the first call, and the irreversibility. This is behavioral context annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the destructive nature and then the confirmation protocol. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description explains the shape of the first response (CONFIRMATION_REQUIRED, what would be deleted, confirm_token), closing the gap for a destructive tool. Nothing an agent needs to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80%, so most params are self-documented; the description adds real value by explaining the provenance and required timing of confirm_token (returned by a prior CONFIRMATION_REQUIRED response, only after approval). It does not touch account/calendar/send_updates, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Permanently delete an event') and immediately flags the destructive scope. An agent can distinguish it from update_event, move_event, and the read-only siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit two-phase protocol: the first call yields CONFIRMATION_REQUIRED, the agent must surface it to the user, and only re-call with the token after explicit approval. This is exactly the when-and-how-when-not guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_permissionsExplain roles and permissionsARead-onlyIdempotent
Explain the role model: which permissions each role grants, what role this session runs as, and what each connected account may do. Use this to answer "why can't you delete that?" accurately instead of guessing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, openWorldHint=true, so the safety and idempotency profile is fully covered. The description adds that it reports the session's own role, which is useful context but not deep behavioral detail. It does not describe caching, scope limits, or output shape, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the verb and the enumerated scope, then the use case. No filler and nothing repeated from the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-param, read-only explanatory tool with no output schema, the description covers when to use it and what it returns. The only minor gap is that it does not sketch the return structure, but it is otherwise complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, which is the baseline-4 case. The description correctly implies a no-input, whole-picture explanation, and nothing about invocation is ambiguous.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Explain) and resource (the role model), then enumerates exactly what it returns: which permissions each role grants, what role the session runs as, and what each connected account may do. This is clearly distinguishable from siblings like get_account or set_account_role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it: to answer questions like "why can't you delete that?" accurately instead of guessing. This names the triggering scenario and the failure mode it prevents, which is strong routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disconnect_accountDisconnect a Google accountADestructive
Revoke this server's access to a Google account, delete its stored tokens and remove it from the registry. Destructive and irreversible: reconnecting requires the user to complete Google consent again. Requires confirmation.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| confirm_token | No | Confirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and readOnlyHint=false, and the description adds substantial context beyond them: what is destroyed (stored tokens), what is removed (registry entry), that it is irreversible, and that a confirmation step gates execution. That is exactly the added-value disclosure expected for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: action, consequences/irreversibility, then the confirmation requirement. Front-loaded and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive action with no output schema, the description covers effect, reversibility, and the confirmation gate; nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including detailed semantics for account and confirm_token, so the schema carries the parameter burden. The description only echoes the confirmation requirement and adds no syntax or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Revoke this server's access to a Google account') and the concrete effects: delete stored tokens, remove from registry. An agent can clearly distinguish this from connect_account among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: destructive, irreversible, and reconnecting requires fresh Google consent, plus 'Requires confirmation'. It does not explicitly name connect_account as the reverse alternative, but the consequence statement effectively routes the decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_available_slotsFind available time slotsARead-onlyIdempotent
Find times when the user is free across all their calendars at once. Merges busy periods from every checked account, then returns slots of the requested length. Always report which accounts were checked, since a slot is only trustworthy if every relevant calendar was included.
| Name | Required | Description | Default |
|---|---|---|---|
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| time_max | Yes | Latest date/time to consider, ISO 8601. A bare date means the end of that day. | |
| time_min | Yes | Earliest date/time to consider, ISO 8601. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| calendars | No | Restrict to these calendar ids. | |
| max_results | No | Maximum slots to return. Default 20. | |
| working_hours | No | Restrict results to working hours. Omit to use 09:00-17:00 Mon-Fri; pass null-equivalent by setting ignore_working_hours. | |
| buffer_minutes | No | Keep this much clear time either side of each slot. Default 0. | |
| duration_minutes | Yes | Required length of the slot, in minutes. | |
| granularity_minutes | No | Align slot starts to this grid. Default 15. | |
| ignore_working_hours | No | Search the entire range including nights and weekends. Default false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description adds genuine behavioral context beyond annotations: it merges busy periods from every checked account and warns that the slot is only trustworthy if every relevant calendar was included — useful for interpreting results and for deciding whether to restrict accounts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, intensely front-loaded, zero filler. Each sentence adds a distinct insight: the merge behavior, the return semantics, and the reporting obligation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, 11-parameter tool with a 100%-covered schema and no output schema, the description covers result interpretation and critical caveats well. It could better address account omission or pagination, but the main operational insight is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so every parameter's meaning is documented in the schema; the description adds no parameter-level syntax or format details. Baseline 3 is appropriate when the schema does all the parameter work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: finds free times, and the description clarifies scope ('across all their calendars at once' and 'Merges busy periods from every checked account'). This distinguishes it from check_freebusy, which likely examines a single account/interval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for finding free/busy windows and hints that accounts matter, but it never names alternatives like check_freebusy or find_cross_account_conflicts, nor states when to prefer it. No when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_cross_account_conflictsFind cross-account conflictsARead-onlyIdempotent
Find events that overlap across different accounts - for example a doctor appointment on personal that collides with a meeting on work. Returns each conflicting pair with the exact overlap window.
| Name | Required | Description | Default |
|---|---|---|---|
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| time_max | Yes | End of the range, ISO 8601. | |
| time_min | Yes | Start of the range, ISO 8601. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| include_same_account | No | Also report overlaps within a single account. Default false, since those are often intentional. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), so the burden is lower, and the description adds genuinely useful behavior: it returns conflicting pairs plus the exact overlap window. It does not, however, mention result limits or what happens when the account list is empty, which would round it out.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the purpose and scope come first, the illustrative example disambiguates rather than pads, and the return shape closes it out. Nothing is redundant with the name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly takes on the job of describing the return value (conflicting pairs with overlap window), and the annotations plus the fully documented schema cover parameters and safety. An agent has everything needed to select and call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents accounts filtering, ISO 8601 time range, timezone, and the include_same_account default. The description adds no syntax or format detail beyond that, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Find events that overlap') and pins the scope to 'across different accounts', which is exactly what distinguishes it from siblings like check_freebusy or list_all_events. The concrete example (personal doctor appointment colliding with a work meeting) removes any ambiguity about the operation's semantics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The cross-account scope implies when this tool is appropriate, but no sibling is named and no exclusion condition is given (e.g. 'use check_freebusy instead when you only care about a single account/slot availability'). Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_accountGet account detailsARead-onlyIdempotent
Show one account in detail: its role, the OAuth access level actually granted by Google, its calendars policy and its effective permissions.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral value by disclosing the nature of the returned data, notably that the OAuth access level reported is the one 'actually granted by Google' and that permissions shown are 'effective', which is not derivable from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One tightly packed sentence that front-loads the action and then enumerates the payload with zero filler. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully compensates by listing the salient returned fields (role, granted OAuth level, calendars policy, effective permissions). It stops short of describing error behavior or what happens when the account id does not resolve, but is adequate for a simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single required parameter, so the schema already explains the account id fully. The description adds no format, aliasing, or resolution detail beyond what the schema provides, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Show one account in detail') and enumerates the content returned: role, OAuth access level granted by Google, calendars policy, effective permissions. It is clearly distinguishable from list_accounts by the singular scope, though it does not name the sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'one account in detail' versus the sibling list_accounts, and the required account id in the schema reinforces it. However, there is no explicit statement of when to use this versus list_accounts or describe_permissions, nor any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventGet one eventARead-onlyIdempotent
Fetch a single event by id. The account must be given explicitly, because an event id is only meaningful within the account it came from.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| calendar | No | Calendar id. Defaults to the account's configured default calendar ("primary" unless changed). | |
| event_id | Yes | The event id, exactly as returned by a list or search tool. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so the safety profile is covered. The description adds non-obvious behavioral context the annotations cannot: the cross-account scoping rule that makes event ids account-bound. It does not cover not-found or wrong-account failure behavior, keeping it below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, no redundancy. The core action is front-loaded and the constraint sentence directly explains the required-parameter semantics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with rich annotations and a fully documented schema, the definition covers what an agent needs to call it. It omits error/failure semantics (e.g., id not found, id from another account), which is a minor remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each parameter is documented, so the baseline would be 3. The description goes further by explaining why 'account' is mandatory (id validity is account-scoped), adding rationale beyond the schema's own 'required whenever more than one account could apply'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch a single event by id'), and the word 'single' implicitly separates it from the list_events/search_events siblings. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear usage rule: the account must be passed explicitly because an event id is only meaningful inside its originating account. It does not name alternatives (list_events, search_events) or say when not to use it, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_routineShow the routine profileARead-onlyIdempotent
Show the routine that drives scheduling: sleep and wake times, the main job window, and every recurring activity with its duration, preferred window and energy level. Read this before proposing a schedule so you can explain what is fixed and what is flexible.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds real value by disclosing the shape of the payload (fixed vs flexible fields), which helps the agent interpret results, though it says nothing about size, pagination, or freshness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler; the content enumeration is front-loaded and the actionable 'read before proposing' instruction closes it. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of describing returns, and it does so thoroughly (times, windows, durations, energy levels). Combined with the read-before-scheduling guidance, an agent has everything needed to call and use it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; the schema fully covers what little there is. The description correctly adds no parameter detail because none exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Show') and resource ('the routine'), then enumerates the exact contents (sleep/wake times, job window, recurring activities with duration, window, energy level). This clearly distinguishes it from sibling mutators like update_routine, reset_routine and propose_schedule.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use condition: 'Read this before proposing a schedule so you can explain what is fixed and what is flexible,' which ties it to the propose_schedule workflow. It does not explicitly name alternatives or when not to use it, but the pre-condition is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsList connected accountsARead-onlyIdempotent
List every connected Google account with its id, email, role, enabled state and what it is permitted to do. Call this first when the user refers to a calendar by name ("my work calendar") so you can map it to an account id.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds value by telling the agent when to invoke it (name-to-account resolution) and what each entry contains, though it does not mention pagination or result size for an open-world listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both front-loaded: the first defines the output fields, the second the trigger condition. Every clause earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only list tool with no output schema, the description covers purpose, returned fields, and the routing trigger. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4. The description correctly implies a no-argument call and enumerates the fields returned per account, matching an empty input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (connected Google accounts) and enumerates the returned fields (id, email, role, enabled state, permissions). This distinguishes it from the singular sibling get_account without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit trigger: 'Call this first when the user refers to a calendar by name' so the agent can map a name to an account id. It does not name a when-not or a specific alternative to use instead, but the condition is concrete and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_all_eventsUnified cross-account event listARead-onlyIdempotent
Unified view of every event across every readable account and calendar in a time range, sorted by start time. Use this when the user asks about their whole schedule, or before reasoning about cross-account conflicts.
| Name | Required | Description | Default |
|---|---|---|---|
| time_max | Yes | End of the range, ISO 8601. A bare date means the end of that day. | |
| time_min | Yes | Start of the range, ISO 8601. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so safety and idempotency are covered. The description adds the union scope and start-time ordering, but says nothing about result volume, pagination, or what 'readable' excludes – gaps that matter for a cross-account aggregation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the scope, followed by the routing guidance. Every clause carries information and nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with no output schema, the description covers scope, ordering, and when to reach for it, which is enough for correct invocation. Minor unaddressed points like pagination or the size of a cross-account result set keep it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so time_min, time_max, and timezone are all documented in the schema. The description only echoes the existence of a time range and adds no format, default, or timezone behavior beyond what the schema supplies, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource (list every event) with an explicit scope that separates it from the single-account siblings: 'across every readable account and calendar in a time range'. The added detail that results are 'sorted by start time' further pins down what the tool returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states a clear trigger ('when the user asks about their whole schedule') and a second intended use ('before reasoning about cross-account conflicts'), which points toward find_cross_account_conflicts. It stops short of naming alternatives or stating when NOT to use it (e.g., for a single account, prefer list_events).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_calendarsList calendarsARead-onlyIdempotent
List the calendars available on one or more connected accounts. Returns the calendar id needed by the event tools, along with the access level the account has on each calendar.
| Name | Required | Description | Default |
|---|---|---|---|
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is fully covered. The description adds that results span multiple connected accounts and include per-calendar access level, but says nothing about pagination, ordering, or permission failures beyond the annotation set; a 3 is fitting given the low bar annotations set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler; the operational fact (what it returns and why it matters) is front-loaded right after the scope statement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully discloses the returned fields (calendar id and access level), which is exactly what an agent needs before chaining into event tools. Minor gaps remain around result ordering/paging and whether calendars are grouped per account, so it is not perfect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single 'accounts' parameter is documented in the schema including its omission default ('every account you are permitted to read'). The description only restates 'one or more connected accounts' without adding format or filtering detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the calendars') and clarifies scope ('on one or more connected accounts'), which cleanly separates it from siblings like list_accounts, list_events, and get_account. It also names the downstream value (the calendar id needed by the event tools), so an agent knows exactly what it gets back.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'returns the calendar id needed by the event tools' implies this is the prerequisite lookup before event operations, giving clear context for when to call it. There are no explicit exclusions or named alternative tools, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList eventsARead-onlyIdempotent
List events in a time range. With no accounts argument this queries every account you may read and every visible calendar on them, which is what you want for questions like "what do I have tomorrow?". Each event is labelled with the account it came from.
| Name | Required | Description | Default |
|---|---|---|---|
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| calendar | No | Calendar id. Defaults to the account's configured default calendar ("primary" unless changed). | |
| time_max | Yes | End of the range. A bare date means the end of that day. | |
| time_min | Yes | Start of the range. ISO 8601, e.g. "2026-09-20" or "2026-09-20T09:00:00". | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| max_results | No | Maximum events per calendar. Default 250. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructive, so the safety profile is covered. The description adds useful behavioral detail — that results are labelled with their source account and that omitting `accounts` fans out across all readable accounts — but says nothing about pagination, rate limits, or result ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, with the broad-scope default and the concrete example front-loaded before the labeling note. Every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with a fully documented schema and annotations covering safety, the description covers the key default-scope behavior and the account labelling of results. With no output schema, a brief note on return shape or ordering/pagination would round it out, but nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already well documented, including the `accounts` omission default and the ISO 8601 / bare-date semantics of the time bounds. The description's restatement of the `accounts` default adds no syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('List events in a time range') and clarifies the default scope when `accounts` is omitted, which is more than a restatement of the name. It does not, however, differentiate itself from close siblings such as `list_all_events` or `search_events`, leaving the agent to infer which listing tool applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete usage context ('what do I have tomorrow?') and explains the condition under which the default broad query happens, which helps the agent decide on argument shape. It stops short of naming when to prefer an alternative such as `search_events` or `check_freebusy`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_eventMove an event between calendarsA
Move an event to a different calendar on the SAME account. Google cannot move an event between two different Google accounts; to do that, create it on the target account and delete the original.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| event_id | Yes | ||
| to_calendar | Yes | Destination calendar id, on the same account. | |
| from_calendar | Yes | Calendar id the event is currently on. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds real behavioral context the annotations don't: a hard same-account constraint imposed by the underlying API. It still omits what happens to the source copy (does the original survive?) and any permission requirements, which is why it is not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the scope constraint front-loaded before the workaround. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter mutation tool with no output schema, the description covers the essential constraint and failure mode. Remaining gaps are the fate of the original event and permission prerequisites, which an agent might still want.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, with to_calendar and from_calendar already documented in the schema ('on the same account', 'currently on'). The description's same-account statement reinforces but does not extend those, and event_id remains undocumented in both places. Baseline 3 fits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (move) and resource (event) and bounds the scope precisely with 'to a different calendar on the SAME account'. It also names the create-then-delete workaround, which separates it from siblings like create_event/delete_event without the agent needing to open those schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not condition (cross-account moves are impossible) and the exact alternative procedure (create on target, delete original). An agent hitting a cross-account request is routed unambiguously.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_schedulePropose a scheduleARead-onlyIdempotent
Read every connected calendar, find the real commitments, and compute a balanced schedule around them. Writes nothing — it returns a plan with a plan_id, an explanation of why each block landed where it did, and an honest workload verdict. Show the plan to the user and get explicit approval before calling apply_schedule.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | How many days to plan. Default 7. | |
| only | No | Plan only these activity ids, e.g. ["dsa","exercise"]. | |
| exclude | No | Skip these activity ids. | |
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| start_date | No | First day to plan, "YYYY-MM-DD". Defaults to tomorrow. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, destructiveHint=false, idempotentHint), but the description adds genuine context beyond them: it writes nothing, and the response carries a plan_id, per-block explanations, and a workload verdict. It does not cover rate limits or the staleness/freshness of the plan, which is the only remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with what it does, then the payload contract, then the approval workflow. Every clause carries information; nothing is redundant with the name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the return-value burden and does so by naming the plan, plan_id, explanations, and workload verdict. Combined with the annotation safety profile and full schema coverage, an agent has everything needed to call it and hand off to apply_schedule.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all six parameters (days, only, exclude, accounts, timezone, start_date) are already documented, including defaults and formats. The description adds no parameter-level meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource chain (read calendars, find commitments, compute a balanced schedule) and explicitly frames itself as the non-writing planner, which separates it from apply_schedule in the same workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit routing: this tool computes the plan, then 'show the plan to the user and get explicit approval before calling apply_schedule.' That names the alternative and the condition that gates it, so no inference is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reset_routineReset the routine to defaultsB
Restore the built-in default routine: early wake, morning exercise, a 10:00–19:00 work-from-anywhere main job with flexible gaps, morning DSA study, midday English practice, and evening part-time work. Overwrites any customisation.
| Name | Required | Description | Default |
|---|---|---|---|
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description says it 'Overwrites any customisation,' which is a destructive effect, while the annotations declare destructiveHint=false. This directly contradicts the safety profile an agent would rely on from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the action and includes a useful enumeration of the default routine. The list is somewhat long but gives concrete meaning to 'default,' so it mostly earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, no-output-schema mutation tool, the description states the effect and overwrite behavior clearly. It could say more about when to prefer update_routine, but the schema and annotations cover most other structural needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single optional timezone parameter is fully documented in the schema. The description adds no parameter-level detail, so it neither helps nor harms beyond the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Restore,' and a specific resource, the built-in default routine, then enumerates exactly what that default contains. An agent can distinguish it from update_routine or get_routine without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies when to use the tool by stating it restores defaults and overwrites customisation, but it does not explicitly contrast this with update_routine, name alternatives, or state when not to use it. The usage context is clear but inferred rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_weekReview a weekARead-onlyIdempotent
Analyse a week that already exists on the calendars: hours per category, how balanced the days are, where the long unbroken stretches are, and whether sleep is being protected. Use this to open a weekly planning session, before proposing the next week.
| Name | Required | Description | Default |
|---|---|---|---|
| week_of | No | Any date in the week to review, "YYYY-MM-DD". Defaults to the current week. | |
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds real value by enumerating what the analysis actually surfaces (category hours, day balance, unbroken stretches, sleep protection), which matters because there is no output schema. It does not mention permissions or rate limits, but openWorldHint partly signals cross-account reach.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, with the analytical content front-loaded before the usage directive. Could be tightened slightly but every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no required parameters, the description does the needed work by describing the shape of the returned analysis and the pre-planning context. An agent has enough to call it correctly; only auth/permission nuances are unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so week_of, accounts and timezone are fully documented in the schema itself. The description adds only the constraint that the week must 'already exist,' which is a marginal semantic addition. Baseline 3 is appropriate when the schema carries the parameter burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb ('Analyse') and resource ('a week that already exists on the calendars'), then enumerates the concrete outputs: hours per category, day balance, long unbroken stretches, sleep protection. This distinguishes it from write-side siblings like propose_schedule and update_routine, which an agent can rule out immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use it: 'open a weekly planning session, before proposing the next week,' which also implies ordering relative to propose_schedule. No explicit when-not or named alternative is given, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_eventsSearch eventsARead-onlyIdempotent
Full-text search across events in a time range. Matches titles, descriptions, locations and attendees. Searches every readable account unless accounts is given.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Text to search for, e.g. "dentist" or "standup". | |
| accounts | No | Account ids to include. If omitted, every account you are permitted to read is included. | |
| time_max | Yes | End of the range, ISO 8601. | |
| time_min | Yes | Start of the range, ISO 8601. | |
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| max_results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered without the description. The description adds matching-scope behavior (titles, descriptions, locations, attendees) and the default cross-account read scope, but says nothing about result caps, ordering, or truncation behavior despite a max_results ceiling of 2500.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, zero filler, with the core capability and its matching scope front-loaded before the account-scoping caveat. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter search with no output schema, the description covers purpose, match fields and default scope, which is enough to invoke correctly. It omits anything about the result shape, ordering, or how max_results bounds output, which is the main remaining gap given there is no output schema to lean on.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 83%, so the schema already documents query, accounts, time_min, time_max and timezone; baseline 3 applies. The description adds a little meaning by clarifying what the `query` string is matched against, but leaves max_results (the only undocumented parameter) unexplained and only restates the accounts default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and technique ("Full-text search") plus the resource (events) and scopes it to a time range, which cleanly separates it from the list_events / list_all_events siblings. It stops short of naming those siblings or explicitly contrasting search from listing, so differentiation is inferable rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the trigger condition (you have a text query and a time window) and clarifies the default account scope, which is genuinely useful. It never states when to prefer this over list_events, list_all_events, or find_cross_account_conflicts, nor any exclusions, so guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_account_enabledEnable or disable an accountA
Enable or disable an account without deleting its tokens. A disabled account is excluded from every operation, including read fan-outs.
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| enabled | Yes | true to enable, false to disable. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=false, but the description adds the non-obvious consequences: tokens are preserved and a disabled account is excluded from every operation, including read fan-outs. That is the key behavioral fact an agent needs and it is not encoded in the annotations. It stops short of stating reversibility or whether enable is idempotent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, no redundancy, and the most decision-relevant fact (tokens are not deleted) is front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter boolean toggle with full schema coverage, annotations for the safety profile, and no output schema, the description covers what is required. The only gap is the absence of routing guidance versus sibling account-management tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (account id, enabled boolean) are already fully documented, including the multiple-account disambiguation hint. The description adds no parameter-level detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb pair (enable/disable) and resource (account), and clarifies the scope of the change: tokens survive. This cleanly separates it from destructive siblings like disconnect_account or delete operations. It doesn't explicitly name a sibling, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the reader infers this is the tool for toggling an account's active state. There is no explicit when/when-not guidance or comparison against disconnect_account or set_account_role, which are the nearest alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_account_roleChange an account roleA
Change the role assigned to a connected account. Note that a role can never exceed the OAuth scopes Google actually granted: promoting a read-only account to editor will not let it write.
| Name | Required | Description | Default |
|---|---|---|---|
| role | Yes | The new role. | |
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false). The description adds a valuable domain caveat beyond annotations: roles cannot exceed granted OAuth scopes, so promotion may silently fail to grant write. This is non-obvious behavioral context that an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no waste; the core action is front-loaded and the caveat follows logically. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-param mutation with annotations and full schema coverage, the description is nearly complete: it states the action and the key caveat. Minor gaps: no mention of permission requirements to change roles or how the change takes effect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema documents both parameters with examples and enum values. The description adds no param syntax or format beyond what the schema provides. Baseline 3 applies when schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('change') and resource ('role assigned to a connected account'), which is clear and distinct from siblings like set_account_enabled or connect_account. It doesn't explicitly name a sibling to differentiate, but the role-focused scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the purpose but there's no explicit when-to-use/when-not guidance, no prerequisites stated, and no alternatives named. The OAuth-scope caveat hints at a constraint but isn't framed as usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_eventUpdate an eventA
Change fields on an existing event. Only the fields you supply are modified; everything else is left alone. The account must be explicit because event ids are account-scoped.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| start | No | New start. Supply both start and end to change the time. | |
| title | No | ||
| account | Yes | The account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply. | |
| calendar | No | Calendar id. Defaults to the account's configured default calendar ("primary" unless changed). | |
| event_id | Yes | ||
| location | No | ||
| timezone | No | IANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone. | |
| attendees | No | Attendee email addresses. Invitations are only emailed if send_updates is set. | |
| description | No | ||
| send_updates | No | Who to email about this change. Defaults to "none" - never notify people unless the user asked you to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-read-only, non-destructive, non-idempotent, so the safety profile is already covered; the description still adds genuinely useful behavior beyond that by explaining patch semantics ("only the fields you supply are modified") and the account-scoping requirement for ids. It omits the default notification behavior, but the schema's send_updates description carries that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and then the two most important behavioral facts. No filler, though the account sentence partially duplicates the schema text rather than earning new ground.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter partial-update tool with no output schema, the description supplies the two things an agent most needs to call it safely: patch semantics and the account requirement. Combined with annotations covering the safety profile and the schema covering defaults, this is adequate for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 55%, so several parameters (end, title, location, description, event_id) are undocumented in both places. The description adds the semantics that unspecified fields are untouched and that account is mandatory due to account-scoped ids, but that largely echoes the schema's own account description; it does not compensate for the coverage gap on the remaining fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Change fields on an existing event") and clarifies that this is a partial update, which distinguishes it from create_event/delete_event. It does not, however, explicitly separate itself from the sibling move_event, which also alters event fields, so an agent must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context for the partial-update behavior and states the account prerequisite, but offers no when-to-use/when-not guidance relative to siblings like move_event or update_routine. Usage is implied rather than routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_routineAdjust the routineA
Change sleep times, daily limits, or one activity in the routine. Use this when the user says things like "make DSA 60 minutes", "I want to wake at 6", or "move part-time work earlier". Changes persist to data/routine.json.
| Name | Required | Description | Default |
|---|---|---|---|
| sleep | No | ||
| activity | No | ||
| max_scheduled_hours_per_day | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, so safety is partially covered. The description adds a genuinely useful persistence detail ('Changes persist to data/routine.json'), but it omits whether changes merge or overwrite existing routine fields and does not confirm the write-confirmation behavior the annotations imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: what it changes, when to use it, and where it persists. Front-loaded with the action, no filler, every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating tool with nested objects, zero schema coverage, and no output schema, the description leaves significant gaps: it never explains the nested sub-fields the active parameters carry, nor whether partial updates require an id (activity.id is required inside the object). It is under-specified given the tool's real complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and there are 3 top-level parameters (sleep, activity, max_scheduled_hours_per_day). The description names the domains but does not explain the nested fields (bedtime, wakeTime, session_minutes, sessions_per_week, weekdays, window) or the unit/format expectations, leaving the agent to infer nested semantics from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States specific verb (change) and the three concrete resources it mutates: sleep times, daily limits, and a single activity. The sibling set contains reset_routine and apply_schedule, and this description's scoping to three specific fields clearly differentiates it from those.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit trigger conditions via example user phrases ('make DSA 60 minutes', 'I want to wake at 6', 'move part-time work earlier'), which tell the agent exactly when this tool is appropriate. It does not name alternatives (e.g. apply_schedule or reset_routine) or exclusions, keeping it out of the 5 tier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
25 tool updates
v1.0.0- First observed
apply_schedule - First observed
check_freebusy - First observed
connect_account - First observed
create_event - First observed
delete_event - First observed
describe_permissions - First observed
disconnect_account - First observed
find_available_slots - First observed
find_cross_account_conflicts - First observed
get_account - First observed
get_event - First observed
get_routine - First observed
list_accounts - First observed
list_all_events - First observed
list_calendars - First observed
list_events - First observed
move_event - First observed
propose_schedule - First observed
reset_routine - First observed
review_week - First observed
search_events - First observed
set_account_enabled - First observed
set_account_role - First observed
update_event - First observed
update_routine
TDQS
Scored across 25 tools
Most tools target a distinct resource+action pair (event CRUD, account admin, free/busy, scheduling). The one real overlap is list_events vs list_all_events: list_events with no `accounts` argument already queries every readable account and calendar, which makes it functionally near-identical to list_all_events, so an agent may hesitate between them. search_events and the free/busy trio are sufficiently differentiated.
Consistent snake_case verb_noun pattern throughout: get_/list_/create_/update_/delete_/set_ prefixes applied uniformly (get_account, list_events, create_event, set_account_role, find_available_slots, propose_schedule). No mixed conventions or vague verbs like 'process' or 'run'.
25 tools sits at the heavy end of the range for a single-domain calendar server. The breadth (multi-account admin, routine management, free/busy analytics, plan propose/apply) justifies many of them, but the surface is larger than needed and some clustering (three free/busy tools, two list/all-event tools) could be consolidated.
Covers event lifecycle (create/update/move/delete/get/list/search), account lifecycle (connect/disconnect/roles/enabled), calendars, availability reasoning and scheduling plans. Minor gaps: no attendee/invite handling, no recurring-event management, and no calendar creation/deletion. Core workflows are otherwise complete with proper confirmation flows for destructive ops.
Maintenance
Related MCP Connectors
GDPR-compliant calendar access for AI assistants: read, create, edit, RSVP. Google, MS 365, Apple.
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
Scheduling infrastructure for AI agents across Google and Microsoft calendars.
Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Google Calendar through OAuth 2.1 authentication, supporting full calendar and event management including creation, updates, deletion, and search across multiple calendars.1-
- AlicenseNot gradedqualityDmaintenanceEnables management of multiple Google Calendar accounts with support for searching, creating, updating, and deleting events on primary calendars through natural language, with encrypted credential storage.15 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage calendars and tasks through natural language, supporting Google Calendar operations like event creation, availability checking, and smart scheduling. It features schedule analysis, task reminders, and meeting time recommendations to streamline productivity.-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to view, create, update, search, and manage Google Calendar events, including multi-account support and availability checks.5 npmBusiness Source 1.1