Skip to main content
Glama

Schedule into free time

schedule

Find conflict-free time and place one or more events — the easiest way to book work without computing slots yourself. (If you already know both an exact start AND end, use write_events create instead.) YOU resolve any relative phrasing ("tomorrow", "next monday", "this afternoon") into the structured fields; this tool does no date parsing. Pass requests, each with a name, an integer durationMinutes (e.g. 90), and EITHER an exact start (local "YYYY-MM-DDTHH:MM") to place there, OR an earliest + latest window (local datetimes, at most 24 hours; it may cross midnight) to search within (map "tomorrow afternoon" → earliest "T13:00", latest "T18:00"; "tomorrow" → "T08:00" to "T22:00"). A request with both start and a window is rejected. For each request: a free exact start is created immediately (the row result has the event). A window request returns ranked options (each a start/end span, also when only one fits) and a commitToken that expires at expiresAt — call confirm_schedule to pick one. Only autoCommitBest: true on a window request books the top pick in one shot and skips that round-trip. Requests are placed in order and kept off each other's committed slots. Each request may carry a requestId so retries don't double-book. Areas and activity types are attached by id only. If the user has a Google Calendar connected with a default sync calendar, a scheduled event is also pushed to Google, the same as a dial create. The response reports per-request results (each with its 0-based index) and, when something was booked, one undoToken that reverts it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
renderNoWhen the user is looking at their reassign dial, set true to repaint it with the updated day in this same call.
requestsYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / requests / items / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "An exact request: book at `start`.",
      -    "properties": {
      -      "activityTypeId": {
      -        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "areaId": {
      -        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "durationMinutes": {
      -        "description": "How long, in whole minutes, e.g. 90.",
      -        "maximum": 1440,
      -        "minimum": 5,
      -        "type": "integer"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      -        "enum": [
      -          "blocking",
      -          "non_blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      -        "type": "string"
      -      },
      -      "requestId": {
      -        "description": "Idempotency key; reuse on retry to avoid double-booking.",
      -        "type": "string"
      -      },
      -      "sourceUrl": {
      -        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      -        "maxLength": 2048,
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "Exact local start \"YYYY-MM-DDTHH:MM\"; place there (alternatives proposed on a conflict).",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "name",
      -      "durationMinutes",
      -      "start"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "A window request: search from `earliest` to `latest`, at most 24 hours.",
      -    "properties": {
      -      "activityTypeId": {
      -        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "areaId": {
      -        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "autoCommitBest": {
      -        "description": "When true, immediately book the top-ranked slot instead of returning `options` + a commitToken. Use for routine one-shot bookings (\"block 2h this afternoon\") to skip the confirm step; leave off (the default) when slots are scarce/contested and you want to review options first.",
      -        "type": "boolean"
      -      },
      -      "durationMinutes": {
      -        "description": "How long, in whole minutes, e.g. 90.",
      -        "maximum": 1440,
      -        "minimum": 5,
      -        "type": "integer"
      -      },
      -      "earliest": {
      -        "description": "Start of the local \"YYYY-MM-DDTHH:MM\" window to search.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      -        "enum": [
      -          "blocking",
      -          "non_blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "latest": {
      -        "description": "End of the search window: after `earliest` and at most 24 hours later; it may be on the next day.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "name": {
      -        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      -        "type": "string"
      -      },
      -      "requestId": {
      -        "description": "Idempotency key; reuse on retry to avoid double-booking.",
      -        "type": "string"
      -      },
      -      "sourceUrl": {
      -        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      -        "maxLength": 2048,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "name",
      -      "durationMinutes",
      -      "earliest",
      -      "latest"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "An exact request: book at `start`.",
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "durationMinutes": {
      +        "description": "How long, in whole minutes, e.g. 90.",
      +        "maximum": 1440,
      +        "minimum": 5,
      +        "type": "integer"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      +        "type": "string"
      +      },
      +      "requestId": {
      +        "description": "Idempotency key; reuse on retry to avoid double-booking. Only this key replays: a request without it is always booked as new.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "Exact local start \"YYYY-MM-DDTHH:MM\"; place there (alternatives proposed on a conflict).",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "durationMinutes",
      +      "start"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "A window request: search from `earliest` to `latest`, at most 24 hours.",
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "autoCommitBest": {
      +        "description": "When true, immediately book the top-ranked slot instead of returning `options` + a commitToken. Use for routine one-shot bookings (\"block 2h this afternoon\") to skip the confirm step. Omitted or false never books, also when only one slot fits: the result is `options` + a commitToken to review first.",
      +        "type": "boolean"
      +      },
      +      "durationMinutes": {
      +        "description": "How long, in whole minutes, e.g. 90.",
      +        "maximum": 1440,
      +        "minimum": 5,
      +        "type": "integer"
      +      },
      +      "earliest": {
      +        "description": "Start of the local \"YYYY-MM-DDTHH:MM\" window to search.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "latest": {
      +        "description": "End of the search window: after `earliest` and at most 24 hours later; it may be on the next day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      +        "type": "string"
      +      },
      +      "requestId": {
      +        "description": "Idempotency key; reuse on retry to avoid double-booking. Only this key replays: a request without it is always booked as new.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "durationMinutes",
      +      "earliest",
      +      "latest"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed5 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • addedInput schema / properties / requests / items / anyOf
      Added value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "An exact request: book at `start`.",
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "durationMinutes": {
      +        "description": "How long, in whole minutes, e.g. 90.",
      +        "maximum": 1440,
      +        "minimum": 5,
      +        "type": "integer"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      +        "type": "string"
      +      },
      +      "requestId": {
      +        "description": "Idempotency key; reuse on retry to avoid double-booking.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "Exact local start \"YYYY-MM-DDTHH:MM\"; place there (alternatives proposed on a conflict).",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "durationMinutes",
      +      "start"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "A window request: search from `earliest` to `latest`, at most 24 hours.",
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "Activity-type id to attach (from the schedule read's `activityTypes`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "Area id to attach (from the schedule read's `areas`); null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "autoCommitBest": {
      +        "description": "When true, immediately book the top-ranked slot instead of returning `options` + a commitToken. Use for routine one-shot bookings (\"block 2h this afternoon\") to skip the confirm step; leave off (the default) when slots are scarce/contested and you want to review options first.",
      +        "type": "boolean"
      +      },
      +      "durationMinutes": {
      +        "description": "How long, in whole minutes, e.g. 90.",
      +        "maximum": 1440,
      +        "minimum": 5,
      +        "type": "integer"
      +      },
      +      "earliest": {
      +        "description": "Start of the local \"YYYY-MM-DDTHH:MM\" window to search.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "latest": {
      +        "description": "End of the search window: after `earliest` and at most 24 hours later; it may be on the next day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "Repeat rule as an RRULE, e.g. \"FREQ=WEEKLY;BYDAY=MO\"; omit for a one-off.",
      +        "type": "string"
      +      },
      +      "requestId": {
      +        "description": "Idempotency key; reuse on retry to avoid double-booking.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "durationMinutes",
      +      "earliest",
      +      "latest"
      +    ],
      +    "type": "object"
      +  }
      +]
    • removedInput schema / properties / requests / items / properties
      Removed value: -{
      -  "activityTypeId": {
      -    "description": "Activity-type id to attach.",
      -    "type": "string"
      -  },
      -  "activityTypeName": {
      -    "description": "Activity type by name instead of id.",
      -    "type": "string"
      -  },
      -  "areaId": {
      -    "description": "Area id to attach.",
      -    "type": "string"
      -  },
      -  "areaName": {
      -    "description": "Area by name instead of id (case/accent-insensitive).",
      -    "type": "string"
      -  },
      -  "autoCommitBest": {
      -    "description": "Flexible requests only (an `earliest`/`latest` window, or neither — NOT an exact `start`). When true, immediately book the top-ranked slot instead of returning `options` + a commitToken. Use for routine one-shot bookings (\"block 2h this afternoon\") to skip the confirm_schedule round-trip; leave off (the default) when slots are scarce/contested and you want to review options first.",
      -    "type": "boolean"
      -  },
      -  "date": {
      -    "description": "Day to place on, ISO \"YYYY-MM-DD\" (you resolve \"tomorrow\" etc.).",
      -    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -    "type": "string"
      -  },
      -  "duration": {
      -    "description": "How long, e.g. \"90m\", \"1h30\", \"2h\", \"45 min\".",
      -    "type": "string"
      -  },
      -  "earliest": {
      -    "description": "Lower bound of an \"HH:MM\" window to search within; omit `start` to use a window.",
      -    "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -    "type": "string"
      -  },
      -  "kind": {
      -    "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      -    "enum": [
      -      "blocking",
      -      "non-blocking",
      -      "reference"
      -    ],
      -    "type": "string"
      -  },
      -  "latest": {
      -    "description": "Upper bound of the \"HH:MM\" search window.",
      -    "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -    "type": "string"
      -  },
      -  "name": {
      -    "description": "Event title, e.g. \"Deep work\", \"Gym\".",
      -    "maxLength": 200,
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  "notes": {
      -    "maxLength": 2000,
      -    "type": "string"
      -  },
      -  "recurrence": {
      -    "description": "Repeat rule (preset or RRULE); omit for a one-off.",
      -    "type": "string"
      -  },
      -  "request_id": {
      -    "description": "Idempotency key; reuse on retry to avoid double-booking.",
      -    "type": "string"
      -  },
      -  "sourceUrl": {
      -    "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      -    "maxLength": 2048,
      -    "type": "string"
      -  },
      -  "start": {
      -    "description": "Exact 24-hour \"HH:MM\" start; given ⇒ place there (alternatives proposed on a conflict).",
      -    "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / requests / items / required
      Removed value: -[
      -  "name",
      -  "duration",
      -  "date"
      -]
    • removedInput schema / properties / requests / items / type
      Removed value: -"object"
  3. Changed1 schema field changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
  4. Changed2 schema fields changed
    • addedInput schema / properties / requests / items / properties / kind
      Added value: +{
      +  "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.",
      +  "enum": [
      +    "blocking",
      +    "non-blocking",
      +    "reference"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / requests / items / properties / sourceUrl
      Added value: +{
      +  "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +  "maxLength": 2048,
      +  "type": "string"
      +}
  5. Changed1 schema field changed
    • addedInput schema / properties / requests / items / properties / autoCommitBest
      Added value: +{
      +  "description": "Flexible requests only (an `earliest`/`latest` window, or neither — NOT an exact `start`). When true, immediately book the top-ranked slot instead of returning `options` + a commitToken. Use for routine one-shot bookings (\"block 2h this afternoon\") to skip the confirm_schedule round-trip; leave off (the default) when slots are scarce/contested and you want to review options first.",
      +  "type": "boolean"
      +}
  6. Changed6 schema fields changed
    • addedInput schema / properties / requests / items / properties / date
      Added value: +{
      +  "description": "Day to place on, ISO \"YYYY-MM-DD\" (you resolve \"tomorrow\" etc.).",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / requests / items / properties / earliest
      Added value: +{
      +  "description": "Lower bound of an \"HH:MM\" window to search within; omit `start` to use a window.",
      +  "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +  "type": "string"
      +}
    • addedInput schema / properties / requests / items / properties / latest
      Added value: +{
      +  "description": "Upper bound of the \"HH:MM\" search window.",
      +  "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +  "type": "string"
      +}
    • addedInput schema / properties / requests / items / properties / start
      Added value: +{
      +  "description": "Exact 24-hour \"HH:MM\" start; given ⇒ place there (alternatives proposed on a conflict).",
      +  "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +  "type": "string"
      +}
    • removedInput schema / properties / requests / items / properties / when
      Removed value: -{
      -  "description": "When, e.g. \"tomorrow morning\", \"next monday at 3pm\", \"2026-06-04T15:30\", \"2026-06-01\".",
      -  "type": "string"
      -}
    • changedInput schema / properties / requests / items / required
      Previous value: -[
      -  "name",
      -  "duration",
      -  "when"
      -]New value: +[
      +  "name",
      +  "duration",
      +  "date"
      +]
  7. First observed

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say the tool is not read-only and not destructive, but the description adds substantial behavioral context: no date parsing, immediate creation for exact starts, ranked options with an expiring commitToken, autoCommitBest behavior, in-order placement, requestId idempotency, Google Calendar push, and an undoToken for reverting bookings. None of this contradicts the annotations.

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?

The description is long but every sentence adds a necessary rule, example, or piece of behavior. It front-loads the core purpose and the main alternative before diving into request semantics, and the complexity of two mutually exclusive request shapes justifies the density.

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?

Despite having no output schema, the description fully explains the response shape: per-request results with 0-based indexes, options, commitToken with expiresAt, and a single undoToken. It also covers idempotency, Google Calendar integration, and ordering constraints, making the tool usable end-to-end.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%, so the description carries the heavy lifting: it explains the exact-start vs earliest/latest window disjunction, concrete examples like mapping 'tomorrow afternoon' to specific datetimes, the 24-hour window cap, and the commit/autoCommit distinction. This goes well beyond the raw schema fields.

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 and resource: 'Find conflict-free time and place one or more events.' It also distinguishes itself from sibling write_events by explicitly saying to use write_events when both an exact start AND end are already known.

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?

The description gives explicit when-to-use guidance: choose write_events for exact start+end, and use schedule for conflict-free scheduling. It also dictates the agent's responsibility to resolve relative phrases into structured fields, warns that a request with both start and a window is rejected, and directs the caller to confirm_schedule when a commitToken is returned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.