Repository navigation
Add MCP tools for team creation, updates, roles and invitations - #8498
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8498 +/- ##
==========================================
+ Coverage 77.07% 77.10% +0.02%
==========================================
Files 466 466
Lines 24943 24972 +29
Branches 6643 6648 +5
==========================================
+ Hits 19226 19255 +29
Misses 5717 5717
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Changing a member's role is now delete-class. Demoting a team's only owner is blocked when the new role is Member but not when it is Viewer or Dashboard (#8580), and those leave the team with no owner and nobody but a platform admin able to restore one. That is less recoverable than anything else here, so it belongs behind destructive tool access, and the caution says which demotions actually bite. The invite description claimed invitation_failed always arrives as HTTP 200 with an error map. It also arrives as a 400 with error as a plain string when the whole call is rejected, for instance on the team user limit. Say both, and mention the route's own 5-calls-per-30-seconds rate limit, which is a second 429 meaning the opposite of too_many_invites. An empty team update answered 200 with the team unchanged, which reads as an edit that never happened; reject it the way the snapshot update tool does. Note that a team created with a team-scoped token falls outside that scope, so the create succeeds and every follow-up call against it does not.
|
Tested all five tools against a running platform. Most of the PR description holds up well, in particular the two calls that were clearly made from reading the routes rather than guessing:
Also confirmed: reserved and duplicate slugs, Four things changed in df928b7: Role changes are now delete-class. Demoting a team's only owner is blocked for Member but not for Viewer or Dashboard, and those succeed and leave the team with zero owners. Proved it on a throwaway team:
The invite route has its own rate limit of 5 calls per 30 seconds, which is a second 429 that means the opposite of An empty team update was a silent no-op, answering 200 with the team unchanged. Also noted on One more from reading rather than running: #8581, |
andypalmi
left a comment
There was a problem hiding this comment.
Checked all five tools against the routes they wrap and everything holds up:
- required vs optional fields on each tool
- the reserved/duplicate slug and
invalid_team_typehandling on create - the trial rules and
billingURLon create - the only-owner demotion asymmetry sitting behind
destructiveHint - both
invitation_failedshapes, plus the separate rate-limit429 - the empty-update guard matching
platform_update_snapshot
Descriptions are accurate, handlers forward what the routes expect, and the tests cover it.
The two route issues this surfaced (#8580 for the owner-orphaning demotion, #8581 for the create route continuing after a 403) are real but correctly left as their own follow-ups rather than holding up this PR.
Closes #7694
Adds five team and membership write tools:
platform_create_teamwrapsPOST /api/v1/teams. The description covers the things an agent can't guess: the team type hashid comes fromplatform_list_team_types, slug rules (createis reserved, uniqueness), the self-service team creation setting for non-admins, the strict trial eligibility rules, and the fact that billing platforms return abillingURLcheckout link the user has to visit.platform_update_teamwraps the name/slug branch ofPUT /api/v1/teams/:teamIdand only exposes those two fields. Type, suspended, features and properties stay out on purpose (the route treats them as mutually exclusive branches, and properties is admin-only).platform_change_member_rolewrapsPUT /api/v1/teams/:teamId/members/:userIdwith role only (the permissions branch needs the RBAC feature and stays out of v1). One reality worth noting from the route: failures like demoting the only owner come back as a generic 403invalid_requestwith no detail, so the description explains the usual causes instead of promising a descriptive error. The SSO-managed-membership block does have a descriptive message and is quoted verbatim.platform_invite_team_memberwrapsPOST /api/v1/teams/:teamId/invitations. The route reports per-person failures as HTTP 200 withcode: invitation_failedand an error map, so the description tells agents to read the body rather than trust the status code. Max 5 per call (429 beyond that), role defaults to Member.platform_resend_team_invitationwrapsPOST /api/v1/teams/:teamId/invitations/:invitationId(no body, extends expiry, 404 for foreign/unknown invitations).