Files
Spencer McGuire 2162aac515 Initial commit: Microsoft To Do for Claude (skill + .mcpb extension)
Claude Code skill (CLI over Microsoft Graph, delegated auth-code + PKCE) and a
Claude Desktop .mcpb extension sharing one dependency-free core client.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:31:48 -06:00

4.4 KiB

Graph API reference for Microsoft To Do

Quick reference for the parts of the Microsoft Graph To Do API this skill relies on. Full docs: https://learn.microsoft.com/graph/api/resources/todo-overview.

Object model

/me/todo/lists                                  todoTaskList[]   (the task lists)
/me/todo/lists/{listId}/tasks                   todoTask[]       (tasks in a list)
/me/todo/lists/{listId}/tasks/{taskId}/checklistItems   checklistItem[]  (subtasks)
  • List ids are long opaque strings (base64-ish), not GUIDs. Resolve by display name when you can.
  • Task ids and checklist item ids are also opaque strings returned by the API; pass them back verbatim.

todoTask properties (create / update)

--fields (and the convenience flags) map to these todoTask properties:

Property JSON value Notes / example
title string Required on create. {"title":"Buy milk"}
body { "content": "...", "contentType": "text"|"html" } --body builds the text form
importance "low" | "normal" | "high" enum — exact strings
status "notStarted" | "inProgress" | "completed" | "waitingOnOthers" | "deferred" enum
dueDateTime dateTimeTimeZone (see below) --due builds this
startDateTime dateTimeTimeZone --start builds this
reminderDateTime dateTimeTimeZone set isReminderOn:true too (--reminder does both)
isReminderOn boolean
categories array of strings must match category names defined in the user's Outlook
recurrence patternedRecurrence object advanced; pass via --fields

Read-only properties returned on GET (don't send them on write): id, createdDateTime, lastModifiedDateTime, completedDateTime, hasAttachments.

dateTimeTimeZone shape

Date/time properties are not plain ISO strings — they're an object:

{ "dueDateTime": { "dateTime": "2026-07-01T17:00:00", "timeZone": "UTC" } }

The CLI's --due / --start / --reminder accept 2026-07-01 (→ midnight) or a full 2026-07-01T17:00:00, and wrap it using TODO_TIMEZONE (default UTC). The timeZone accepts IANA (America/Denver) or Windows (Mountain Standard Time) zone names. To set one manually via --fields, supply the full object.

Marking complete

Set status to "completed" (the done command does this). Graph stamps completedDateTime automatically. Setting status back to notStarted/ inProgress reopens it.

Querying tasks (OData)

The CLI maps flags to OData query options on /me/todo/lists/{listId}/tasks:

  • --filter$filter. To Do supports a subset of OData. Useful ones:
    • status ne 'completed' — open tasks
    • status eq 'completed'
    • importance eq 'high'
    • lastModifiedDateTime gt 2026-06-01T00:00:00Z
    • combine with and / or
    • Note: filtering directly on dueDateTime is limited; prefer fetching and sorting client-side for due-date views.
  • --orderby$orderby, e.g. dueDateTime/dateTime asc (nested path), or importance desc, lastModifiedDateTime desc, createdDateTime asc.
  • --select → projects which properties come back: title,status,dueDateTime.
  • --top → page size; --all follows @odata.nextLink to return every page.

Escaping quotes

OData string literals use single quotes; a literal single quote is doubled: title eq 'O''Brien'. In the shell, wrap the whole --filter value in double quotes.

Checklist items (subtasks)

A checklistItem has just displayName and isChecked:

node scripts/todo.mjs checklist-add   --list "Work" --id "<TASK_ID>" --name "Draft outline"
node scripts/todo.mjs checklist-check --list "Work" --id "<TASK_ID>" --item "<ITEM_ID>"   # --uncheck to undo

Response shape (reads)

Reads return tasks simplified to:

{
  "id": "<opaque task id>",
  "title": "Renew SSL cert",
  "status": "inProgress",
  "importance": "high",
  "isReminderOn": true,
  "dueDateTime": { "dateTime": "2026-07-01T00:00:00.0000000", "timeZone": "UTC" },
  "reminderDateTime": { "dateTime": "2026-06-30T09:00:00.0000000", "timeZone": "UTC" },
  "body": { "content": "Use the prod ACME account", "contentType": "text" },
  "categories": [],
  "createdDateTime": "2026-06-16T10:00:00Z",
  "lastModifiedDateTime": "2026-06-16T12:30:00Z"
}

id is the value you pass to get, update, done, and delete. Empty/unset properties are omitted from the simplified shape.