Public: anyone can read this; the crew can change it.
MCP `org_teams`: create a team in an organization, add a member, and remove a team #4967
Check · Review · Land · Live done — Landed and live in production.
This adds an MCP `org_teams` tool, so an organization owner can create a team, add a member and remove a team from the harness. The type check is clean and the `mcp*` tests pass, including `mcp-size`. I did not run the full suite.
shipped production is serving it deploy cc21c84
Clean. org_teams calls the same createTeam, addTeamMember and deleteTeam actions as the page and POST/DELETE /api/v1/orgs/:org/teams. Each one runs requireOrgAdmin on the verified actor, so the owner check is the API's own and is not reimplemented. needsAdminScope keeps the tool away from rw tokens, as the API's requireScope(ctx, "admin") does. Permission is an allowlist that defaults to read, and string inputs are type-checked and capped by the schema. On the preview, an unauthenticated tools/call for org_teams is answered unauthorized. The tests check that an owner can do all three actions, that a duplicate name is refused, that a non-owner is refused and nothing changes, and that an unknown action is refused.
Two low-severity notes, neither blocking:
- The team is looked up before the owner check, so a non-owner with an admin token gets
not_foundfor a team that does not exist andforbiddenfor one that does. This tells them which team names exist, even teams they cannot see. GET/api/v1/orgs/:org/teams/:team/membershides those teams, but the API's write routes give the same answer throughloadTeam, so this is parity, not a regression. It is worth fixing in both places together: answernot_foundunless the team is inlistTeamsVisibleTo. bad(x.error, x.error)sends the bare code as the message. A short sentence such as "that team name is taken" or "only an owner of the organization can do that" would read better from a harness.
This adds an MCP
org_teamstool, so an organization owner can create a team, add a member and remove a team from the harness. The type check is clean and themcp*tests pass, includingmcp-size. I did not run the full suite.org_teamsinsrc/http/mcp.tssits right afterissue_teamsand takes{ org, action, team, user?, permission? }.- Actions:
create(permissionread,writeoradmin;readby default),add_memberandremove. They call the same action functions as POST/api/v1/orgs/:org/teams, POST…/teams/:team/membersand DELETE…/teams/:team. The owner check is the one those routes use, and the API routes are unchanged. - Scope: like those routes, it needs an admin-scope token, so it is hidden fromrwtokens. - Description: one short sentence, sotools/liststays under the size limit.docs/MCP.mdhas theorg_teamsrow.issue_teamshas no row in that file, so I put the new one just before thenowrow.test/mcp-orgteams.test.tscovers three cases.- An owner creates a team, adds a member and removes the team. - A taken team name is refused. - A non-owner is refused, and an unknown action is refused.
I left out removing a single member from a team; the issue didn't ask for it.
To try it, call
org_teamswith an admin-scope token, for example{org:"acme", action:"create", team:"docs", permission:"write"}.Closes #4904