From m365
Manages Microsoft Teams via Graph API: lists teams/channels/members/meetings, adds/removes members, checks usage, troubleshoots access for MSP support.
npx claudepluginhub wyre-technology/msp-claude-plugins --plugin m365This skill uses the workspace's default tool permissions.
Microsoft Teams is the collaboration hub for most M365 customers. MSP support tasks include troubleshooting access issues, managing team membership, reviewing channel structure, and investigating meeting problems. All Teams data is accessible through Microsoft Graph.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Designs, implements, and audits WCAG 2.2 AA accessible UIs for Web (ARIA/HTML5), iOS (SwiftUI traits), and Android (Compose semantics). Audits code for compliance gaps.
Microsoft Teams is the collaboration hub for most M365 customers. MSP support tasks include troubleshooting access issues, managing team membership, reviewing channel structure, and investigating meeting problems. All Teams data is accessible through Microsoft Graph.
| Object | Description | API Resource |
|---|---|---|
| Team | Top-level workspace | /teams/{id} |
| Channel | Conversation thread within a team | /teams/{id}/channels/{id} |
| Member | User in a team (owner or member) | /teams/{id}/members |
| Meeting | Online meeting or channel event | /me/onlineMeetings |
| Tab | App integration in a channel | /teams/{id}/channels/{id}/tabs |
GET /v1.0/users/{userId}/joinedTeams?$select=id,displayName,description,visibility
Response:
{
"value": [
{
"id": "team-guid",
"displayName": "Engineering",
"description": "Engineering team workspace",
"visibility": "private"
}
]
}
GET /v1.0/groups?$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&$select=id,displayName,description,createdDateTime,visibility
GET /v1.0/teams/{teamId}?$select=id,displayName,description,isArchived,memberSettings,guestSettings,messagingSettings
GET /v1.0/teams/{teamId}/channels?$select=id,displayName,description,membershipType,createdDateTime
Channel types:
standard — Open to all team membersprivate — Invite-only subset of team membersshared — Shared with external users or other teamsGET /v1.0/teams/{teamId}/members?$select=id,displayName,email,roles
Roles: owner or member (empty array = member)
POST /v1.0/teams/{teamId}/members
Content-Type: application/json
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [],
"user@odata.bind": "https://graph.microsoft.com/v1.0/users/{userId}"
}
To add as owner: set "roles": ["owner"]
DELETE /v1.0/teams/{teamId}/members/{memberId}
POST /v1.0/teams
Content-Type: application/json
{
"template@odata.bind": "https://graph.microsoft.com/v1.0/teamsTemplates('standard')",
"displayName": "IT Support",
"description": "Internal IT support team",
"visibility": "private",
"members": [
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": ["owner"],
"user@odata.bind": "https://graph.microsoft.com/v1.0/users/{ownerUserId}"
}
]
}
POST /v1.0/teams/{teamId}/archive
Content-Type: application/json
{
"shouldSetSpoSiteReadOnlyForMembers": true
}
GET /v1.0/teams/{teamId}/channels/{channelId}/messages?$top=20&$orderby=createdDateTime desc
GET /v1.0/users/{userId}/calendar/events?$filter=start/dateTime ge '2024-01-15T00:00:00' and isOnlineMeeting eq true&$select=subject,start,end,organizer,onlineMeeting&$orderby=start/dateTime
GET /v1.0/users/{userId}/onlineMeetings/{meetingId}?$select=subject,startDateTime,endDateTime,joinUrl,participants
POST /v1.0/users/{userId}/onlineMeetings
Content-Type: application/json
{
"startDateTime": "2024-01-20T14:00:00Z",
"endDateTime": "2024-01-20T15:00:00Z",
"subject": "IT Onboarding Session"
}
/joinedTeams)GET /v1.0/groups?$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&$select=id,displayName
Then for each team:
GET /v1.0/teams/{teamId}/members?$filter=roles/any(r:r eq 'owner')
Empty result = orphaned team, security risk.
List teams with external members:
GET /v1.0/teams/{teamId}/members?$filter=startsWith(email,'#EXT#')
External accounts have #EXT# in their UPN pattern.
| Symptom | Check | Resolution |
|---|---|---|
| Can't join a team | Check visibility (private requires invite) | Add via API or admin invite |
| Missing from channel | Private channel membership | Add to private channel specifically |
| Can't see messages | Guest/external user restrictions | Review guest settings in team |
| Meeting join fails | License (Teams not in SKU) | Assign Teams service plan |
| Missing in directory | Not synced from AD | Check Azure AD Connect sync |
| Task | Microsoft Graph Permission |
|---|---|
| List joined teams | Team.ReadBasic.All |
| List all tenant teams | Directory.Read.All |
| Read team members | TeamMember.Read.All |
| Add/remove members | TeamMember.ReadWrite.All |
| Create teams | Team.Create |
| Archive teams | TeamSettings.ReadWrite.All |
| Read messages | ChannelMessage.Read.All |