Skip to content

5.4-a Team read tools (phase 1) #7693

Description

@andypalmi

Parent: #7673 (5.4 Teams and membership)
Tool file: forge/ee/lib/mcp/tools/teams.js (extend)

Read tools for the team resource: team lookups, membership, the team audit log, and team-scoped data and packages (npm packages, git tokens, shared library). All fold into teams.js following the one-file-per-resource convention (a tool lives in the file for the noun it is about). Tools that describe a different resource have moved out of this issue: instance lists to instances.js, application statuses to applications.js, provisioning tokens to devices.js, and team types to platform.js.

readOnlyHint: true.

Tool Endpoint Scope Annotation
platform_get_team_by_slug GET /teams/slug/:teamSlug team:read read
platform_get_team_instance_counts GET /teams/:teamId/instance-counts team:read read
platform_check_team_slug_availability POST /teams/check-slug team:create read (readOnly, no mutation)
platform_get_team_membership GET /teams/:teamId/user (none, self) read
platform_list_team_members GET /teams/:teamId/members team:user:list read
platform_list_team_invitations GET /teams/:teamId/invitations team:user:invite read
platform_get_team_audit_log GET /teams/:teamId/audit-log team:audit-log read
platform_export_team_audit_log GET /teams/:teamId/audit-log/export team:audit-log read
platform_list_team_npm_packages GET /teams/:teamId/npm/packages team:packages:read read
platform_list_team_git_tokens GET /teams/:teamId/git/tokens team:git:tokens:list read
platform_list_library_entries GET /storage/library/:libraryId/* library:entry:list read

Design notes:

  • check-slug is POST but non-mutating; annotate readOnlyHint: true so a read-only PAT can use it. The value "create" is reserved and always rejected.
  • platform_get_team_instance_counts requires instanceType (remote|hosted): the route's second preHandler returns 400 unless it is one of those two values, so it is effectively required.
  • platform_list_team_invitations is gated by team:user:invite (Owner), so a non-Owner read-only PAT gets a 403 even though the tool is annotated read.
  • Plan-gated per team (not per user role): npm, gitIntegration, shared-library. When the plan does not include the feature the route returns a 404 independent of the PAT's permissions; the tool surfaces a clear "feature not enabled for this team" message. The response body differs per surface: npm, gitIntegration, and shared-library return a plain Not Found. shared-library defaults to enabled (feature default true), unlike the other three which default false.
  • platform_list_team_git_tokens uses the tokenList view and never surfaces the raw stored PAT.
  • GET /npm/userToken is a presence check (returns {} / 404), not a token, and stays excluded as part of the Owner-scoped sensitive token surface.

Scopes to allow-list + access-tag (#7445):
team:user:list (read), team:user:invite (read), team:audit-log (read), team:packages:read (read), team:git:tokens:list (read), library:entry:list (read), team:create (read, for check-slug). team:read is already present from the shipped team tools.

Removed from the user:expert-mcp allow-list on this branch (the scopes move with their tools): team-type:list and team-type:read move to platform.js; team:device:provisioning-token:list moves to devices.js.

Tests:

  • Read tools allowed for read-only PAT.
  • check-slug usable by a read-only PAT (annotated readOnlyHint: true).
  • Database list/get output does not contain credentials.password.
  • Git-token list never surfaces the raw stored PAT.
  • Feature-disabled team returns the descriptive gate error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    storyA user-oriented description of a feature

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions