M365 Planner
by @felox63
Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports...
clawhub install m365-planner-v2π About This Skill
name: m365-planner description: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions. license: MIT version: 1.2.3
M365 Planner Skill
Manage Microsoft 365 Planner through Microsoft Graph API.
What's New in v1.2.3
os.homedir() instead of hardcoded pathsWhat's New in v1.2.2
os.homedir() instead of hardcoded /home/claw/.openclaw/.envWhat's New in v1.2.1
What's New in v1.1.0
mgc CLIPrerequisites
1. Azure AD App Registration (see Setup below)
2. Node.js v18+ with @microsoft/microsoft-graph-client and axios
3. M365 Group (not Security Group or Distribution List!)
Quick Start
# Test connection
node scripts/test-connection.jsList all plans
node scripts/list_plans.jsList plans for specific group
node scripts/list_plans.js Create plan
node scripts/create_plan.js "Project Name" Create task
node scripts/create_task.js "Task Title"Delete completed tasks
node scripts/cleanup_verlaengerungen.js "" ""
Setup: Azure AD App Registration
Step 1: Create App Registration
Azure Portal:
1. https://portal.azure.com β Azure Active Directory β App registrations
2. "New registration"
3. Name: M365-Planner-Integration
4. Supported account types: Accounts in this organizational directory only
5. Redirect URI: None (Client Credentials Flow)
Or via Azure CLI:
az login
az ad app create --display-name "M365-Planner-Integration" --sign-in-audience "AzureADMyOrg"
Note the Application (client) ID from the output.Step 2: Add API Permissions
Important: Use Application Permissions (not Delegated)!
Azure Portal:
1. App β API permissions β Add a permission
2. Microsoft Graph β Application permissions
3. Add:
- Group.Read.All (not Group.ReadWrite.All β sufficient for Planner)
- Tasks.ReadWrite.All
4. Grant Admin Consent: Click "Grant admin consent for [Tenant]"!
Or via Azure CLI:
APP_ID="your-app-id"Group.Read.All
az ad app permission add \
--id $APP_ID \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions 5b567253-7703-48e2-861c-caed61531407=RoleTasks.ReadWrite.All
az ad app permission add \
--id $APP_ID \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=RoleAdmin Consent
az ad app permission admin-consent --id $APP_ID
Step 3: Create Client Secret
Azure Portal:
1. App β Certificates & secrets β Client secrets β New client secret
2. Description: OpenClaw Integration
3. Expires: 24 months (Maximum)
4. Copy values immediately! β Only shown once
Or via Azure CLI:
az ad app credential reset \
--id $APP_ID \
--append \
--display-name "OpenClaw Integration"
Step 4: Configure Environment
Store credentials in ~/.openclaw/.env:
# Microsoft 365 Planner Credentials
M365_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
M365_CLIENT_SECRET="your-secret-value"
M365_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Secure permissions:
chmod 600 ~/.openclaw/.env
Step 5: Test Connection
node scripts/test-connection.js
Expected output:
β
Access Token successfully received!
π Test: M365 Groups...
3 groups found:
- My Team β
M365/Planner-capable
β
Connection successful!
Important Notes
M365 Groups vs. Security Groups
Planner ONLY works with M365 Groups!
Check groups:
node scripts/test-connection.js
Shows all groups with status "β
M365/Planner-capable".Create M365 Group (if none exists):
If-Match Header (ETag)
All update and delete operations require the If-Match header!
Planner uses Optimistic Concurrency Control. Requests fail without ETag.
Delete Example:
// Wrong β
await client.api(/planner/tasks/${taskId}).delete();// Correct β
const task = await client.api(/planner/tasks/${taskId}).get();
await client.api(/planner/tasks/${taskId})
.headers({ 'If-Match': task['@odata.etag'] })
.delete();
Update Example:
const task = await client.api(/planner/tasks/${taskId}).get();
await client.api(/planner/tasks/${taskId})
.headers({ 'If-Match': task['@odata.etag'] })
.update({ percentComplete: 50 });
Group-Based API Endpoints
Do NOT use:
GET /planner/plans β (requires complex filter)
Use:
GET /groups/{group-id}/planner/plans β
Example:
const plans = await client.api(/groups/${groupId}/planner/plans).get();
Recurring Tasks
Microsoft Planner supports native recurring tasks!
In Planner Web UI or Mobile App: 1. Open task 2. Click "Repeat" 3. Choose frequency: Daily, Weekly, Monthly, Yearly, Custom
Example:
β οΈ API Limitation: The Graph API does not support creating recurring tasks directly. Recurring tasks must be set up via Planner UI.
Common Operations
Plans
| Operation | Script |
|-----------|--------|
| List all plans | node scripts/list_plans.js |
| Create plan | node scripts/create_plan.js |
| Delete plan | node scripts/delete_plan.js |
Buckets
| Operation | Script |
|-----------|--------|
| List buckets | Integrated in list_plans.js |
| Create bucket | node scripts/create_bucket.js |
| Delete bucket | node scripts/delete_bucket.js |
Tasks
| Operation | Script |
|-----------|--------|
| List tasks | Integrated in list_plans.js |
| Create task | node scripts/create_task.js |
| Update task | node scripts/update_task.js |
| Delete task | node scripts/delete_task.js |
| Cleanup | node scripts/cleanup_verlaengerungen.js |
Helper Scripts
test-connection.js
Tests connection to Microsoft Graph:node scripts/test-connection.js
list_plans.js
Shows all plans in an M365 Group with:# Without argument: Shows all available groups
node scripts/list_plans.jsWith Group ID: Shows plans for specific group
node scripts/list_plans.js
create_plan.js
Creates a new plan with default buckets:node scripts/create_plan.js "Project Alpha"
cleanup_verlaengerungen.js
Cleans up completed tasks from a bucket:node scripts/cleanup_verlaengerungen.js "" ""
Example:
node scripts/cleanup_verlaengerungen.js abc-123 "My Project" "Completed"
Troubleshooting
Error: Insufficient privileges
Cause: Admin consent not granted
Solution:
az ad app permission admin-consent --id
Or in Azure Portal: API permissions β Grant admin consentError: Group not found
Cause: Planner only works with M365 Groups
Solution: 1. Check if it's an M365 Group (has mail attribute) 2. Security Groups/Distribution Lists don't work 3. Create new M365 Group (Teams or Admin Center)
Error: The If-Match header must be specified
Cause: Update/Delete without ETag
Solution:
// First get task for ETag
const task = await client.api(/planner/tasks/${id}).get();
// Then update/delete with If-Match header
await client.api(/planner/tasks/${id})
.headers({ 'If-Match': task['@odata.etag'] })
.delete();
Error: This entity set must be queried with a filter
Cause: /planner/plans endpoint requires filter
Solution: Use group-based endpoint:
// Wrong β
const plans = await client.api('/planner/plans').get();// Correct β
const plans = await client.api(/groups/${groupId}/planner/plans).get();
Error: Cannot find module '@microsoft/microsoft-graph-client'
Cause: Node.js packages not installed
Solution:
cd ~/.openclaw/workspace/skills/m365-planner
npm install
Dependencies
Install packages locally in skill directory:
cd ~/.openclaw/workspace/skills/m365-planner
npm install @microsoft/microsoft-graph-client axios
References
Changelog
v1.2.3 (2026-04-18)
os.homedir() for cross-system compatibilityv1.2.2 (2026-04-18)
os.homedir() instead of hardcoded /home/claw/.openclaw/.envv1.2.1 (2026-04-18)
v1.1.0 (2026-04-17)
v1.0.0 (2023-01-19)
π‘ Examples
# Test connection
node scripts/test-connection.jsList all plans
node scripts/list_plans.jsList plans for specific group
node scripts/list_plans.js Create plan
node scripts/create_plan.js "Project Name" Create task
node scripts/create_task.js "Task Title"Delete completed tasks
node scripts/cleanup_verlaengerungen.js "" ""
βοΈ Configuration
1. Azure AD App Registration (see Setup below)
2. Node.js v18+ with @microsoft/microsoft-graph-client and axios
3. M365 Group (not Security Group or Distribution List!)
π Tips & Best Practices
Error: Insufficient privileges
Cause: Admin consent not granted
Solution:
az ad app permission admin-consent --id
Or in Azure Portal: API permissions β Grant admin consentError: Group not found
Cause: Planner only works with M365 Groups
Solution: 1. Check if it's an M365 Group (has mail attribute) 2. Security Groups/Distribution Lists don't work 3. Create new M365 Group (Teams or Admin Center)
Error: The If-Match header must be specified
Cause: Update/Delete without ETag
Solution:
// First get task for ETag
const task = await client.api(/planner/tasks/${id}).get();
// Then update/delete with If-Match header
await client.api(/planner/tasks/${id})
.headers({ 'If-Match': task['@odata.etag'] })
.delete();
Error: This entity set must be queried with a filter
Cause: /planner/plans endpoint requires filter
Solution: Use group-based endpoint:
// Wrong β
const plans = await client.api('/planner/plans').get();// Correct β
const plans = await client.api(/groups/${groupId}/planner/plans).get();
Error: Cannot find module '@microsoft/microsoft-graph-client'
Cause: Node.js packages not installed
Solution:
cd ~/.openclaw/workspace/skills/m365-planner
npm install