Parent: #7675 (5.6 Device groups (fleet))
Tool file: new forge/ee/lib/mcp/tools/deviceGroups.js
readOnlyHint: false, destructiveHint: false. Creation, edits, membership changes, and settings are distinct endpoints and scopes, so they stay separate tools.
| Tool |
Endpoint |
Scope |
Annotation |
platform_create_device_group |
POST /applications/:applicationId/device-groups |
application:device-group:create |
write |
platform_update_device_group |
PUT /applications/:applicationId/device-groups/:groupId |
application:device-group:update |
write |
platform_update_device_group_membership |
PATCH /applications/:applicationId/device-groups/:groupId |
application:device-group:membership:update |
write |
platform_update_device_group_settings |
PUT /applications/:applicationId/device-groups/:groupId/settings |
application:device-group:update |
write |
Design notes:
- All routes require the
deviceGroups feature (404 otherwise). Surface as a descriptive "device groups not enabled for this team" error.
update_device_group accepts name, description, and targetSnapshotId (string or null) - setting targetSnapshotId is how a group's deployed snapshot is pinned/cleared.
PUT /:groupId/settings carries a Member-only { env } field restriction in the handler, but its scope is application:device-group:update (Owner), so under standard team RBAC only Owners reach it and they may send the full settings body (the declared schema only names env). The Member-only branch is reachable solely via app-specific granted permissions, not ordinary roles.
Scopes to allow-list + access-tag (#7445): application:device-group:create (write), application:device-group:update (write), application:device-group:membership:update (write).
Tool definitions (description + zod inputSchema):
platform_create_device_group: {
description: 'Create a device group in an application.',
inputSchema: z.object({
applicationId: z.string().describe('Application hashid to create the group in'),
name: z.string().describe('Name for the new device group (required)'),
description: z.string().optional().describe('Optional description for the group')
})
}
platform_update_device_group: {
description: 'Update a device group. Setting targetSnapshotId pins the group deployed snapshot; passing null clears it.',
inputSchema: z.object({
applicationId: z.string().describe('Application hashid the group belongs to'),
groupId: z.string().describe('Device group hashid to update'),
name: z.string().optional().describe('New group name'),
description: z.string().optional().describe('New group description'),
targetSnapshotId: z.string().nullable().optional().describe('Snapshot hashid to pin as the group target, or null to clear it')
})
}
platform_update_device_group_membership: {
description: 'Change the membership of a device group. Combine add/remove for incremental changes, or use set to replace the entire membership.',
inputSchema: z.object({
applicationId: z.string().describe('Application hashid the group belongs to'),
groupId: z.string().describe('Device group hashid whose membership to change'),
add: z.array(z.string()).optional().describe('Device hashids to add to the group'),
remove: z.array(z.string()).optional().describe('Device hashids to remove from the group'),
set: z.array(z.string()).optional().describe('Device hashids to set as the exact group membership')
})
}
platform_update_device_group_settings: {
description: 'Update a device group settings. The declared schema names only env; under standard team RBAC only Owners can update device group settings, and only Owners may send settings fields other than env.',
inputSchema: z.object({
applicationId: z.string().describe('Application hashid the group belongs to'),
groupId: z.string().describe('Device group hashid whose settings to update'),
env: z.array(z.record(z.any())).optional().describe('Environment variable objects for the group')
})
}
Tests:
- Write tools rejected for read-only PAT.
- Feature-disabled team returns the descriptive gate error.
update_device_group_settings write is accepted for an Owner PAT.
Parent: #7675 (5.6 Device groups (fleet))
Tool file: new
forge/ee/lib/mcp/tools/deviceGroups.jsreadOnlyHint: false,destructiveHint: false. Creation, edits, membership changes, and settings are distinct endpoints and scopes, so they stay separate tools.platform_create_device_groupPOST /applications/:applicationId/device-groupsapplication:device-group:createplatform_update_device_groupPUT /applications/:applicationId/device-groups/:groupIdapplication:device-group:updateplatform_update_device_group_membershipPATCH /applications/:applicationId/device-groups/:groupIdapplication:device-group:membership:updateplatform_update_device_group_settingsPUT /applications/:applicationId/device-groups/:groupId/settingsapplication:device-group:updateDesign notes:
deviceGroupsfeature (404 otherwise). Surface as a descriptive "device groups not enabled for this team" error.update_device_groupacceptsname,description, andtargetSnapshotId(string or null) - settingtargetSnapshotIdis how a group's deployed snapshot is pinned/cleared.PUT /:groupId/settingscarries a Member-only{ env }field restriction in the handler, but its scope isapplication:device-group:update(Owner), so under standard team RBAC only Owners reach it and they may send the full settings body (the declared schema only namesenv). The Member-only branch is reachable solely via app-specific granted permissions, not ordinary roles.Scopes to allow-list + access-tag (#7445):
application:device-group:create(write),application:device-group:update(write),application:device-group:membership:update(write).Tool definitions (description + zod inputSchema):
Tests:
update_device_group_settingswrite is accepted for an Owner PAT.