117 lines
5.7 KiB
Markdown
117 lines
5.7 KiB
Markdown
|
|
# 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 "<TASK_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).
|
||
|
|
```
|