/install m365-planner-v2
M365 Planner Skill
Manage Microsoft 365 Planner through Microsoft Graph API.
What's New in v1.2.3
- 🌍 English Documentation – Complete translation for international ClawHub availability
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded paths - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
What's New in v1.2.2
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded/home/claw/.openclaw/.env - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
What's New in v1.2.1
- ✅ Generic Scripts – No hardcoded Group-IDs or Plan names anymore
- ✅ Command-Line Parameters – All scripts accept IDs as arguments
- ✅ List Plans Improved – Shows all groups when no ID provided
- ✅ Flexible Cleanup – Works with any plans/buckets
- ✅ ClawHub-ready – No project-specific data included
What's New in v1.1.0
- ✅ Node.js Scripts – Standalone scripts without
mgcCLI - ✅ If-Match Header Support – Correct ETag handling for updates/deletes
- ✅ Group-Based API – Direct access via M365 Group-ID
- ✅ Recurring Tasks – Note about native Planner recurrence feature
- ✅ Cleanup Scripts – Automated task cleanup
Prerequisites
- Azure AD App Registration (see Setup below)
- Node.js v18+ with
@microsoft/microsoft-graph-clientandaxios - M365 Group (not Security Group or Distribution List!)
Quick Start
# Test connection
node scripts/test-connection.js
# List all plans
node scripts/list_plans.js
# List plans for specific group
node scripts/list_plans.js \x3Cgroup-id>
# Create plan
node scripts/create_plan.js "Project Name" \x3Cgroup-id>
# Create task
node scripts/create_task.js \x3Cplan-id> \x3Cbucket-id> "Task Title"
# Delete completed tasks
node scripts/cleanup_verlaengerungen.js \x3Cgroup-id> "\x3Cplan-name>" "\x3Cbucket-name>"
Setup: Azure AD App Registration
Step 1: Create App Registration
Azure Portal:
- https://portal.azure.com → Azure Active Directory → App registrations
- "New registration"
- Name:
M365-Planner-Integration - Supported account types:
Accounts in this organizational directory only - 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:
- App → API permissions → Add a permission
- Microsoft Graph → Application permissions
- Add:
Group.Read.All(not Group.ReadWrite.All – sufficient for Planner)Tasks.ReadWrite.All
- 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=Role
# Tasks.ReadWrite.All
az ad app permission add \
--id $APP_ID \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role
# Admin Consent
az ad app permission admin-consent --id $APP_ID
Step 3: Create Client Secret
Azure Portal:
- App → Certificates & secrets → Client secrets → New client secret
- Description:
OpenClaw Integration - Expires: 24 months (Maximum)
- 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!
- ✅ M365 Group – Has Exchange mailbox, Teams, Planner (recognizable by mail attribute)
- ❌ Security Group – Only for permissions, no Planner
- ❌ Distribution List – Only for email distribution, no Planner
Check groups:
node scripts/test-connection.js
Shows all groups with status "✅ M365/Planner-capable".
Create M365 Group (if none exists):
- Microsoft 365 Admin Center → Groups → Add a group
- Or Teams: Create new team (automatically creates M365 Group)
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:
- Open task
- Click "Repeat"
- Choose frequency: Daily, Weekly, Monthly, Yearly, Custom
Example:
- "Domain renewal example.com" → Repeat yearly
- "Check backup" → Repeat weekly
⚠️ 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 \x3Cname> \x3Cgroup-id> |
| Delete plan | node scripts/delete_plan.js \x3Cplan-id> |
Buckets
| Operation | Script |
|---|---|
| List buckets | Integrated in list_plans.js |
| Create bucket | node scripts/create_bucket.js \x3Cplan-id> \x3Cname> |
| Delete bucket | node scripts/delete_bucket.js \x3Cbucket-id> |
Tasks
| Operation | Script |
|---|---|
| List tasks | Integrated in list_plans.js |
| Create task | node scripts/create_task.js \x3Cplan-id> \x3Cbucket-id> \x3Ctitle> |
| Update task | node scripts/update_task.js \x3Ctask-id> --percent-complete 50 |
| Delete task | node scripts/delete_task.js \x3Ctask-id> |
| Cleanup | node scripts/cleanup_verlaengerungen.js \x3Cgroup-id> "\x3Cplan-name>" "\x3Cbucket-name>" |
Helper Scripts
test-connection.js
Tests connection to Microsoft Graph:
- Request access token
- Display tenant information
- List available M365 Groups
- Check Planner capability
node scripts/test-connection.js
list_plans.js
Shows all plans in an M365 Group with:
- Buckets and their tasks
- Task status (completed/in progress/open)
- Percentage progress indicator
# Without argument: Shows all available groups
node scripts/list_plans.js
# With Group ID: Shows plans for specific group
node scripts/list_plans.js \x3Cgroup-id>
create_plan.js
Creates a new plan with default buckets:
- To Do
- In Progress
- Done
node scripts/create_plan.js "Project Alpha" \x3Cgroup-id>
cleanup_verlaengerungen.js
Cleans up completed tasks from a bucket:
- Deletes tasks with 100% progress
- Keeps open tasks
- Correct If-Match header handling
node scripts/cleanup_verlaengerungen.js \x3Cgroup-id> "\x3Cplan-name>" "\x3Cbucket-name>"
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 \x3Capp-id>
Or in Azure Portal: API permissions → Grant admin consent
Error: Group not found
Cause: Planner only works with M365 Groups
Solution:
- Check if it's an M365 Group (has mail attribute)
- Security Groups/Distribution Lists don't work
- 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
- Planner API Overview
- Setup Guide
- Common Patterns
- Microsoft Graph API Docs
- Planner REST API Reference
Changelog
v1.2.3 (2026-04-18)
- 🌍 English Documentation – Complete translation for international ClawHub availability
- 🔧 Portability – Env path uses
os.homedir()for cross-system compatibility - 🧹 Security Audit – No hardcoded IDs, names, or domains
v1.2.2 (2026-04-18)
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded/home/claw/.openclaw/.env - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
v1.2.1 (2026-04-18)
- ✅ Generic Scripts – No hardcoded Group-IDs or Plan names anymore
- ✅ Command-Line Parameters – All scripts accept IDs as arguments
- ✅ List Plans Improved – Shows all groups when no ID provided
- ✅ Flexible Cleanup – Works with any plans/buckets
- ✅ ClawHub-ready – No project-specific data included
v1.1.0 (2026-04-17)
- ✅ Node.js Scripts instead of mgc CLI
- ✅ If-Match Header Support for updates/deletes
- ✅ Group-based API Endpoints
- ✅ Test-Connection Script with M365 Group Detection
- ✅ List Plans Script with Bucket/Task overview
- ✅ Cleanup Script for completed tasks
- ✅ Documentation for recurring tasks (native Planner feature)
- ✅ Troubleshooting Section expanded
v1.0.0 (2023-01-19)
- Initial version with mgc CLI
- Azure AD Setup Guide
- Basic CRUD operations
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install m365-planner-v2 - After installation, invoke the skill by name or use
/m365-planner-v2 - Provide required inputs per the skill's parameter spec and get structured output
What is M365 Planner?
Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... It is an AI Agent Skill for Claude Code / OpenClaw, with 90 downloads so far.
How do I install M365 Planner?
Run "/install m365-planner-v2" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is M365 Planner free?
Yes, M365 Planner is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does M365 Planner support?
M365 Planner is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created M365 Planner?
It is built and maintained by Felix M. (@felox63); the current version is v1.2.3.