Skip to main content
Glama

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 v3

Each 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

  1. Requirements

  2. Quick start

  3. Google Cloud setup

  4. Connecting five accounts

  5. Connecting to Claude

  6. Planning assistant

  7. Roles and permissions

  8. Security model

  9. Tools

  10. Example prompts

  11. Testing

  12. Troubleshooting

  13. Configuration reference


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 doctor

Google 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

  1. Open https://console.cloud.google.com/projectcreate.

  2. Name it, e.g. calendar-mcp, and click Create.

  3. Make sure it is selected in the project picker at the top.

2. Enable the Calendar API

  1. Go to APIs & Services → Library.

  2. Search for Google Calendar API.

  3. Click Enable.

  1. Go to APIs & Services → OAuth consent screen.

  2. Choose a user type:

    • External — required for personal @gmail.com accounts.

    • Internal — only if every account is in one Google Workspace organisation. This is simpler: no verification, no user cap.

  3. Fill in the app name, your support email, and your developer email.

4. Add the scopes

Add exactly these, and no others:

Scope

Why

openid

binds each token to an identity

.../auth/userinfo.email

records which Google account a token belongs to

.../auth/calendar.readonly

list calendars, read events, query free/busy

.../auth/calendar.events

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

  1. Go to APIs & Services → Credentials → Create Credentials → OAuth client ID.

  2. Application type: Desktop app. ← this matters

  3. Name it, then click Create.

  4. 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 add http://127.0.0.1:42813/oauth2callback as an authorized redirect URI and keep MCP_OAUTH_PORT pinned 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_write

Each run:

  1. starts a loopback listener on 127.0.0.1,

  2. opens Google's consent screen with prompt=consent select_account,

  3. 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,

  4. verifies the returned id_token and records the email,

  5. encrypts the tokens to data/tokens/<id>.token.enc.json,

  6. 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 doctor

This 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 deletes

Connecting 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.json

  • macOS: ~/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.js

Or 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 mcp-remote

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; src/index.ts is the only file that assumes stdio.

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

plan_week

Review the week just gone, propose the week ahead, apply on approval

plan_tomorrow

One day, planned around what is already booked

daily_check_in

Short morning briefing: what is fixed, what clashes, best focus block

find_time_for

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

physical

1-2.5h after waking

jogging

high

peak analytical window, 1.5-4h after waking

DSA study

medium

anywhere with decent energy

part-time work, English

low

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 created

The gate is structural, not advisory:

  • propose_schedule holds 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  sleep

Tuning 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.configure

Role → permissions

Permission

viewer

editor

scheduler

admin

calendar.read

calendar.search

calendar.freebusy

calendar.create

calendar.update

calendar.reschedule

calendar.delete

account.list

account.connect

account.disconnect

account.configure

routine.read

plan.propose

routine.manage

permission.read

permission.manage

system.configure

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

personal

Primary personal calendar

admin

yes

yes

personal2

Secondary personal calendar

viewer

no

no

work1

Full-time job

editor

yes

no

work

Part-time job

editor

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. personal2 holds read/write OAuth scopes but the viewer role, and its effective permission is read-only. Widening the OAuth grant, or editing accounts.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 to viewer and 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.

  1. Session role — does MCP_PRINCIPAL_ROLE grant this permission at all?

  2. Account role — does this account's role grant it?

  3. Account overridesdeniedPermissions wins over everything, including admin and the wildcard.

  4. 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 finding work inside 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.log is reassigned to stderr at startup.

Account isolation

  • One OAuth2Client per 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 doctor cross-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 concurrent apply_schedule calls 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_schedule refuses 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_KEY and 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

list_accounts

every account with role, state and effective permissions

get_account

one account in detail, including granted OAuth access

describe_permissions

the role model, and why something was denied

list_calendars

calendars across accounts, with Google access roles

list_events

events in a range; fans out across accounts by default

list_all_events

unified cross-account timeline, sorted

search_events

full-text search across accounts

get_event

one event (account required — ids are account-scoped)

check_freebusy

busy periods plus a merged timeline

find_cross_account_conflicts

overlapping events across accounts

find_available_slots

free slots across every checked calendar

Write (editor / scheduler and above)

Tool

Notes

create_event

routes to one account; AMBIGUOUS_ACCOUNT rather than guessing

update_event

patch semantics; time changes also need calendar.reschedule

move_event

between calendars within one account (Google cannot move across accounts)

Planning

Tool

Notes

get_routine

Sleep, work hours, every recurring activity

propose_schedule

Computes a plan; writes nothing; returns a plan_id

apply_schedule

Creates the events, two-phase confirmed

review_week

Hours per category, busiest/lightest day, long stretches

update_routine

Change sleep, limits or one activity (scheduler/admin)

reset_routine

Restore the defaults (scheduler/admin)

Admin

Tool

Notes

delete_event

destructive; two-phase confirmation

connect_account

returns the command for the user to run; consent happens in their browser

disconnect_account

destructive; revokes at Google then deletes locally

set_account_role

warns if the role exceeds the granted OAuth scopes

set_account_enabled

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_account returns the exact command instead.

  • delete_calendar / ACL editing. Out of scope, and the reason the broad calendar scope 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_conflicts with accounts: ["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 reports checked_accounts so you can see nothing was missed.

"Create this event on my work calendar." create_event with account: "work" → created; the response says account_resolution: "explicit".

"Create a meeting tomorrow at 10am." (no calendar named) create_event with 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: work is editor, 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 Google

Suite

Covers

tests/unit/rbac.test.ts

role expansion, the four gates, the account matrix

tests/unit/account-isolation.test.ts

per-account vaults, crossed-token detection, traversal, concurrency

tests/unit/routing.test.ts

ambiguity refusal, explicit routing, no fallback

tests/unit/confirm.test.ts

token binding, replay across accounts, expiry, single use

tests/unit/scheduling.test.ts

interval algebra, conflicts, slots, DST, +05:45 zones

tests/unit/auth.test.ts

client binding, refresh persistence, crypto, redaction

tests/unit/tool-exposure.test.ts

visibility per role, annotation correctness

tests/unit/planner.test.ts

placement rules, consistency, WFA gaps, overload honesty

tests/integration/tools.test.ts

real handlers end-to-end with a fake Google layer

tests/integration/planning.test.ts

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_DENIED

  • editor can create and update, cannot delete

  • scheduler can schedule; admin can manage accounts

  • personal token → personal vault only; a swapped file is rejected

  • a confirm token from business cannot delete on work

  • an 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

  1. npm run build — the config points at dist/, not src/.

  2. Use absolute paths in claude_desktop_config.json.

  3. Restart Claude Desktop fully.

  4. Check MCP_PRINCIPAL_ROLE: viewer legitimately hides every write tool.

  5. Run the server manually — it prints startup errors to stderr:

    node dist/index.js
  6. Claude 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_write

CALENDAR_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

GOOGLE_CLIENT_ID

OAuth client id

GOOGLE_CLIENT_SECRET

OAuth client secret

MCP_MASTER_KEY

token-vault encryption passphrase

MCP_PRINCIPAL_ROLE

admin

session role ceiling

MCP_DEFAULT_TIMEZONE

host zone

IANA zone, e.g. Asia/Jakarta

MCP_DATA_DIR

./data

registry and vault location

MCP_OAUTH_PORT

42813

loopback port for npm run auth

MCP_DYNAMIC_TOOL_EXPOSURE

true

hide tools the session role cannot use

MCP_CONFIRMATION_TTL_SECONDS

300

confirm-token lifetime

MCP_PLAN_TTL_SECONDS

3600

how long a proposed schedule stays applicable

MCP_LOG_LEVEL

info

debug/info/warn/error/silent

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.json

Back 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, doctor

rbac/ imports nothing from google/. The authorization layer is reusable for any resource, and is tested without a network.


Sources


Licence

MIT

Available Tools

25 tools
apply_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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoAccount to create the events on. Required when more than one account is eligible.
plan_idYesThe plan_id returned by propose_schedule.
calendarNoCalendar id on that account. Defaults to its default calendar.
confirm_tokenNoConfirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described.
skip_activitiesNoActivity ids the user declined, e.g. ["part-time"]. Everything else is created.

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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/busyA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
time_maxYesEnd of the range, ISO 8601.
time_minYesStart of the range, ISO 8601.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
calendarsNoRestrict to these calendar ids.

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoRole to assign. Start with the least privilege that meets the need.viewer
accessNoOAuth scopes to request. read_only cannot be escalated later without re-authorizing.read_only
accountYesThe short id to register, e.g. "work" or "family".

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesEnd time, ISO 8601.
startYesStart time, ISO 8601. Interpreted in `timezone` if it has no offset.
titleYesEvent title.
accountNoThe 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_dayNoCreate an all-day event.
calendarNoCalendar id. Defaults to the account's configured default calendar ("primary" unless changed).
locationNo
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
attendeesNoAttendee email addresses. Invitations are only emailed if send_updates is set.
recurrenceNoRRULE strings, e.g. ["RRULE:FREQ=WEEKLY;BYDAY=MO"].
descriptionNo
send_updatesNoWho to email about this change. Defaults to "none" - never notify people unless the user asked you to.
reminder_minutesNoPopup reminder, minutes before start.

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 eventA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
calendarNoCalendar id. Defaults to the account's configured default calendar ("primary" unless changed).
event_idYes
send_updatesNoWho to email about this change. Defaults to "none" - never notify people unless the user asked you to.
confirm_tokenNoConfirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 permissionsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 accountA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
confirm_tokenNoConfirmation token returned by a previous CONFIRMATION_REQUIRED response. Only supply this after the user has explicitly approved the exact action described.

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 slotsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
time_maxYesLatest date/time to consider, ISO 8601. A bare date means the end of that day.
time_minYesEarliest date/time to consider, ISO 8601.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
calendarsNoRestrict to these calendar ids.
max_resultsNoMaximum slots to return. Default 20.
working_hoursNoRestrict results to working hours. Omit to use 09:00-17:00 Mon-Fri; pass null-equivalent by setting ignore_working_hours.
buffer_minutesNoKeep this much clear time either side of each slot. Default 0.
duration_minutesYesRequired length of the slot, in minutes.
granularity_minutesNoAlign slot starts to this grid. Default 15.
ignore_working_hoursNoSearch the entire range including nights and weekends. Default false.

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 conflictsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
time_maxYesEnd of the range, ISO 8601.
time_minYesStart of the range, ISO 8601.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
include_same_accountNoAlso report overlaps within a single account. Default false, since those are often intentional.

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 detailsA
Read-onlyIdempotent

Show one account in detail: its role, the OAuth access level actually granted by Google, its calendars policy and its effective permissions.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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 eventA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
calendarNoCalendar id. Defaults to the account's configured default calendar ("primary" unless changed).
event_idYesThe event id, exactly as returned by a list or search tool.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 profileA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 accountsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 listA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
time_maxYesEnd of the range, ISO 8601. A bare date means the end of that day.
time_minYesStart of the range, ISO 8601.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 calendarsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 eventsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
calendarNoCalendar id. Defaults to the account's configured default calendar ("primary" unless changed).
time_maxYesEnd of the range. A bare date means the end of that day.
time_minYesStart of the range. ISO 8601, e.g. "2026-09-20" or "2026-09-20T09:00:00".
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
max_resultsNoMaximum events per calendar. Default 250.

TDQS

A3.8/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
event_idYes
to_calendarYesDestination calendar id, on the same account.
from_calendarYesCalendar id the event is currently on.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 scheduleA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoHow many days to plan. Default 7.
onlyNoPlan only these activity ids, e.g. ["dsa","exercise"].
excludeNoSkip these activity ids.
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
start_dateNoFirst day to plan, "YYYY-MM-DD". Defaults to tomorrow.

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.

TDQS

B3.3/5.0
Behavior1/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 weekA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
week_ofNoAny date in the week to review, "YYYY-MM-DD". Defaults to the current week.
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 eventsA
Read-onlyIdempotent

Full-text search across events in a time range. Matches titles, descriptions, locations and attendees. Searches every readable account unless accounts is given.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesText to search for, e.g. "dentist" or "standup".
accountsNoAccount ids to include. If omitted, every account you are permitted to read is included.
time_maxYesEnd of the range, ISO 8601.
time_minYesStart of the range, ISO 8601.
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
max_resultsNo

TDQS

A3.5/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
enabledYestrue to enable, false to disable.

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleYesThe new role.
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNo
startNoNew start. Supply both start and end to change the time.
titleNo
accountYesThe account id to act on, e.g. "work" or "personal". Required whenever more than one account could apply.
calendarNoCalendar id. Defaults to the account's configured default calendar ("primary" unless changed).
event_idYes
locationNo
timezoneNoIANA timezone for interpreting and displaying times, e.g. "Asia/Jakarta". Defaults to the server timezone.
attendeesNoAttendee email addresses. Invitations are only emailed if send_updates is set.
descriptionNo
send_updatesNoWho to email about this change. Defaults to "none" - never notify people unless the user asked you to.

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
sleepNo
activityNo
max_scheduled_hours_per_dayNo

TDQS

A3.7/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness2/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 25 tool updatesv1.0.0
    • First observedapply_schedule
    • First observedcheck_freebusy
    • First observedconnect_account
    • First observedcreate_event
    • First observeddelete_event
    • First observeddescribe_permissions
    • First observeddisconnect_account
    • First observedfind_available_slots
    • First observedfind_cross_account_conflicts
    • First observedget_account
    • First observedget_event
    • First observedget_routine
    • First observedlist_accounts
    • First observedlist_all_events
    • First observedlist_calendars
    • First observedlist_events
    • First observedmove_event
    • First observedpropose_schedule
    • First observedreset_routine
    • First observedreview_week
    • First observedsearch_events
    • First observedset_account_enabled
    • First observedset_account_role
    • First observedupdate_event
    • First observedupdate_routine

TDQS

A3.9/5.0

Scored across 25 tools

Disambiguation4/5

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.

Naming Consistency5/5

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'.

Tool Count3/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables 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.
    -