# Claude-MSTodo Connect Claude to **Microsoft To Do** via the Microsoft Graph API, with full read/write (CRUD) over task lists, tasks, and checklist items (subtasks). This is a sibling to [Claude-SharepointLists](../Claude-SharepointLists), built the same way — a dependency-free core Graph client (`graph.mjs`) wrapped by a small CLI and packaged as a Claude Code **skill**. The one fundamental difference is **authentication**: | | SharePoint Lists | **Microsoft To Do** | |---|---|---| | Auth model | App-only (client credentials) | **Delegated (browser, auth-code + PKCE)** | | Why | SharePoint supports application permissions | To Do has **no** app-only access — `/me/todo` needs a user token | | Secrets | tenant + client id + **client secret** | client id only (**public client**, no secret) | | First run | works immediately | **`login` once** (opens browser); refresh token cached | > A browser flow is used rather than device-code because device-code is commonly > blocked by Conditional Access (AADSTS53003). Two ways to use it, sharing one core Graph client (`graph.mjs`): | Form | Best for | Entry point | |---|---|---| | **Skill** | Claude Code on your own machine | `.claude/skills/ms-todo/` | | **Desktop extension (`.mcpb`)** | Claude Desktop, distributed org-wide | `mcp-extension/` | ## Repo layout ``` . ├── .claude/skills/ms-todo/ # the skill (Claude Code) │ ├── SKILL.md # how the skill works + usage │ ├── .env.example # config template (.env is git-ignored) │ ├── scripts/ │ │ ├── todo.mjs # CLI: login|logout|test|lists|tasks|get|create|update|done|delete|checklist… │ │ └── lib/graph.mjs # shared, dependency-free Graph client (MSTodoClient) — single source of truth │ └── references/ │ ├── setup.md # Entra app registration walkthrough (public client + loopback redirect) │ └── graph-api.md # todoTask field formats + OData query reference └── mcp-extension/ # Claude Desktop extension (imports the same graph.mjs) ├── manifest.json # .mcpb manifest (baked client/tenant id, user_config) ├── server/index.mjs # MCP server (stdio) exposing todo_* tools ├── scripts/sync-core.mjs # copies the canonical graph.mjs into the bundle └── README.md # build + install + admin setup ``` For Claude Desktop, build and distribute the extension — see [`mcp-extension/README.md`](mcp-extension/README.md). (Claude Desktop can't run Claude Code skills; it loads MCP servers, so the `.mcpb` is the right vehicle.) ## Prerequisites (one-time) An Entra (Azure AD) **public client** app registration with the delegated `Tasks.ReadWrite` permission and a loopback redirect URI (`http://localhost` + `http://127.0.0.1`) under the Mobile-and-desktop platform. The full walkthrough is in [`references/setup.md`](.claude/skills/ms-todo/references/setup.md). You end up needing just one value: `TODO_CLIENT_ID` (and optionally `TODO_TENANT_ID`). There is **no client secret** — To Do is a personal/delegated resource, so you sign in as yourself once and the refresh token is cached in a git-ignored file. ## Quick start ```bash cp .claude/skills/ms-todo/.env.example .claude/skills/ms-todo/.env # set TODO_CLIENT_ID (and TODO_TENANT_ID if not "common") cd .claude/skills/ms-todo/scripts node todo.mjs login # open the printed URL, enter the code, approve node todo.mjs test # -> { ok: true, signedInAs, listCount, lists: [...] } node todo.mjs lists node todo.mjs tasks --list "Work" --filter "status ne 'completed'" --orderby "dueDateTime/dateTime asc" node todo.mjs create --list "Work" --title "Renew SSL cert" --due 2026-07-01 --importance high node todo.mjs done --list "Work" --id "" ``` See [SKILL.md](.claude/skills/ms-todo/SKILL.md) for the full command set and [references/graph-api.md](.claude/skills/ms-todo/references/graph-api.md) for task field formats and OData query details. ## Commands | Command | Purpose | |---|---| | `login` / `logout` | Browser sign-in (auth-code+PKCE) / forget the cached sign-in | | `test` | Verify auth; show signed-in user and task lists | | `lists` | List all task lists | | `list-create` / `list-update` / `list-delete` | Manage task lists | | `tasks` | Query tasks (`--filter`/`--select`/`--orderby`/`--top`/`--all`) | | `get` | Get one task by id | | `create` / `update` / `done` / `delete` | Manage tasks | | `checklist` / `checklist-add` / `checklist-check` / `checklist-delete` | Manage subtasks | ## Security notes - **Delegated auth = the cached token acts as you.** Anyone with read access to `scripts/.token-cache.json` can use your To Do. It's written `0600` and git-ignored — keep it that way; `logout` deletes it. - There is **no client secret** to leak; the public-client app id is not a secret. - The skill is for the signed-in user's own tasks. To act as another user you'd sign in as them (or, for an MCP server, run a separate cache per account). ## Graduating to an MCP server The Graph + auth logic lives entirely in [`graph.mjs`](.claude/skills/ms-todo/scripts/lib/graph.mjs) (`MSTodoClient`, zero dependencies), so it drops straight into an `@modelcontextprotocol/sdk` server — expose `listTasks`/`getTask`/`createTask`/`updateTask`/`deleteTask` and the list/checklist methods as tools. The only extra step vs. an app-only server: run `login` once on the host to seed the token cache the server reads. See the note at the bottom of [`references/setup.md`](.claude/skills/ms-todo/references/setup.md). ```