Microsoft To Do
Microsoft To Do via Microsoft Graph. List task lists, read tasks, create tasks, update tasks, and mark tasks complete.
Description
name: microsoft-todo description: "Microsoft To Do via Microsoft Graph. List task lists, read tasks, create tasks, update tasks, and mark tasks complete." metadata: openclaw: category: "productivity" primaryEnv: "MS_TODO_CLIENT_ID" requires: bins: ["python3"] env: ["MS_TODO_CLIENT_ID", "MS_TODO_TENANT_ID"]
microsoft-todo
Use Microsoft Graph To Do endpoints for personal task lists and tasks.
When to Use
Use this skill when the user wants to:
- list Microsoft To Do task lists
- read tasks from a list
- create, update, complete, or delete tasks
- authenticate a Microsoft personal account or Entra-backed account for To Do
Do not use this skill for:
- Outlook mail APIs unrelated to To Do
- app-only Graph auth flows
- non-Microsoft task systems
Inputs Needed
client_idfrom an Entra app registrationtenant_idfor work/school accounts, orconsumersfor personal Outlook/Hotmail/Live accounts- delegated Graph permissions:
Tasks.ReadWrite
Secret and Config Storage
Use the OS-native user config directory as the default. That matches common cross-platform practice and keeps secrets out of shell startup files.
Default config locations:
- Linux:
$XDG_CONFIG_HOME/microsoft-todoor~/.config/microsoft-todo - macOS:
~/Library/Application Support/microsoft-todo - Windows:
%APPDATA%\\microsoft-todo
Use that config directory for:
client_idtenant_idtoken.jsondevice_code.json
Avoid putting bearer tokens or refresh tokens in:
~/.bashrc~/.zshrc- committed
.envfiles
For quick local-only usage, the bundled Python helper also loads scripts/.env if it exists. That is an override path, not the primary default for published usage.
Supported environment overrides:
MS_TODO_TENANT_IDMS_TODO_CLIENT_IDMS_TODO_CONFIG_DIRMS_TODO_TOKEN_FILEMS_TODO_DEVICE_FILE
Auth Model
Microsoft To Do on Graph uses delegated permissions. Authenticate as a signed-in user with device-code flow.
Required delegated permissions:
Tasks.ReadTasks.ReadWrite- optional
offline_access
Create a Microsoft Entra app registration, then store its IDs locally:
mkdir -p ~/.config/microsoft-todo
echo "YOUR_TENANT_ID_OR_consumers" > ~/.config/microsoft-todo/tenant_id
echo "YOUR_CLIENT_ID" > ~/.config/microsoft-todo/client_id
Where to get them:
tenant_id: Azure Portal -> Microsoft Entra ID -> Overview ->Tenant IDclient_id: Azure Portal -> Microsoft Entra ID -> App registrations -> your app ->Application (client) ID- For personal Microsoft accounts, use
consumersinstead of the directory tenant ID in auth URLs
Authentication requirements in Entra:
- In
Authentication, setAllow public client flowstoYes - If shown, under
Mobile and desktop applications, enable the platform and keep public client flows enabled - Device-code flow will fail with
AADSTS7000218if the app is still treated as a confidential client - For personal Microsoft accounts, set supported account types to include personal accounts
Bundled helper:
scripts/ms_todo_auth.pyhandles device-code auth, token polling, refresh-token exchange, access-token output, and resolved path inspection
Optional local override file:
scripts/.env.exampleshows the supported variables for a portable setup- copy it to
scripts/.envonly if you explicitly want local overrides
Get an Access Token
Create the default config directory and store the app IDs:
python3 scripts/ms_todo_auth.py show-paths
Then place:
tenant_idin the reportedtenant_fileclient_idin the reportedclient_file
Request a device code:
python3 scripts/ms_todo_auth.py device-code
The response includes user_code, verification_uri, and device_code, and saves the full payload to device_code.json.
Open the verification_uri, enter the user_code, sign in, then poll for tokens:
python3 scripts/ms_todo_auth.py poll-token
This saves the full token response to token.json but does not echo raw token JSON with bearer or refresh secrets to stdout.
Refresh later when needed:
python3 scripts/ms_todo_auth.py refresh-token
This also updates token.json without echoing raw token JSON secrets to stdout.
Extract the bearer token when needed:
ACCESS_TOKEN=$(python3 scripts/ms_todo_auth.py access-token)
Do not hardcode access tokens in the skill. They expire.
Example with env-var overrides:
MS_TODO_TENANT_ID=consumers \
MS_TODO_CLIENT_ID="your-client-id" \
python3 scripts/ms_todo_auth.py device-code
Example with portable local overrides in scripts/.env:
MS_TODO_TENANT_ID=consumers
MS_TODO_CLIENT_ID=your-client-id
MS_TODO_CONFIG_DIR=./state
Base Request Pattern
ACCESS_TOKEN=$(python3 scripts/ms_todo_auth.py access-token)
curl -s "https://graph.microsoft.com/v1.0/me/todo/lists" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" | jq
Common Operations
List task lists
curl -s "https://graph.microsoft.com/v1.0/me/todo/lists" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq
Get one task list
LIST_ID="your-list-id"
curl -s "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq
List tasks in a list
LIST_ID="your-list-id"
curl -s "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID/tasks" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq
Create a task
LIST_ID="your-list-id"
curl -s -X POST "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID/tasks" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Buy milk",
"importance": "normal"
}' | jq
Update a task
LIST_ID="your-list-id"
TASK_ID="your-task-id"
curl -s -X PATCH "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID/tasks/$TASK_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Buy milk and eggs",
"status": "inProgress"
}' | jq
Mark a task complete
LIST_ID="your-list-id"
TASK_ID="your-task-id"
curl -s -X PATCH "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID/tasks/$TASK_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "completed"
}' | jq
Delete a task
LIST_ID="your-list-id"
TASK_ID="your-task-id"
curl -i -X DELETE "https://graph.microsoft.com/v1.0/me/todo/lists/$LIST_ID/tasks/$TASK_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Notes
- To Do is user-scoped. Use delegated auth, not app-only auth.
- Hardcoding
tenant_idandclient_idis acceptable for a personal setup, but store them in the platform config directory unless you intentionally choosescripts/.envfor a local portable copy. - A bearer token comes from the token endpoint after device-code sign-in. It is not shown in the Azure dashboard.
- If you want automatic renewal, save the refresh token from
token.jsonand exchange it for a new access token later. poll-tokenandrefresh-tokenpersist the full token payload totoken.json; stdout is summarized so raw token JSON secrets are not printed.- For personal Outlook/Hotmail/Live accounts, set
tenant_idtoconsumersfor device-code and token requests.
Validation
The skill is working when:
python3 scripts/ms_todo_auth.py show-pathsreports the expected config locationspython3 scripts/ms_todo_auth.py device-codereturns auser_codepython3 scripts/ms_todo_auth.py poll-tokenwrites the platform configtoken.jsonGET /v1.0/me/todo/listsreturns a JSONvaluearray
Common Failure Modes
AADSTS7000218: app is not configured as a public clientAADSTS700016onconsumers: app does not allow personal Microsoft accountsMailboxNotEnabledForRESTAPI: account auth worked, but mailbox/To Do access is not usable for that account/authority combinationauthorization_pending: complete the device-code sign-in in the browser and retry token polling
Links
- Graph To Do overview: https://learn.microsoft.com/en-us/graph/api/resources/todo-overview
- Device code flow: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code
User Setup Checklist
Before using this skill, do this once in Azure Portal and once on your local machine:
- Go to Azure Portal -> Microsoft Entra ID -> App registrations -> New registration.
- Name the app something like
Microsoft To Do Skill. - Set supported account types to
Accounts in any organizational directory and personal Microsoft accounts. - Create the app, then copy the
Application (client) ID. - If you want personal Microsoft accounts such as Outlook/Hotmail/Live, use
consumersas the tenant value for this skill. - If you only want a specific work or school tenant, use that Entra tenant ID instead.
- Open the app's
Authenticationpage and enableAllow public client flows. - If Azure shows a
Mobile and desktop applicationsplatform section, enable it and keep the app as a public client. - Open
API permissions, add Microsoft Graph delegated permissions, and includeTasks.ReadWrite. - Keep
offline_accessavailable for refresh-token renewal during device-code auth. - Run
python3 scripts/ms_todo_auth.py show-pathsto see where this skill expects local config files. - Create the reported
tenant_idfile andclient_idfile with your chosen tenant value and copied client ID. - Run
python3 scripts/ms_todo_auth.py device-code, open the returnedverification_uri, and enter theuser_code. - After sign-in completes, run
python3 scripts/ms_todo_auth.py poll-token. - Confirm that
token.jsonwas written, then usepython3 scripts/ms_todo_auth.py access-tokenor callGET /v1.0/me/todo/lists.
If device-code auth fails, re-check these settings first:
- account type allows personal accounts if you are using
consumers - public client flows are enabled
- Microsoft Graph delegated permission
Tasks.ReadWriteis present
Reviews (0)
No reviews yet. Be the first to review!
Comments (0)
No comments yet. Be the first to share your thoughts!