FlowFuse / FlowFuse/flowfuse

5.6-b Write tools, non-destructive (phase 2)

Open
#7,700 0 comments 0 reactions 0 assignees View on GitHub
story
Dominant language
JavaScript
Stars
400
Forks
89
Avg merge
1d 20h
Merged PRs (30d)
149

Description

**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.

**Tool definitions (description + zod inputSchema):**
```js
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.

---

Contributor guide

Open the contributing guide

Research direction

Start with the new forge/ee/lib/mcp/tools/deviceGroups.js file and trace the four specified endpoints, scopes, annotations, and deviceGroups feature gate. Add the schemas and descriptive disabled-feature handling, then run the listed tests for read-only PAT rejection, feature-disabled teams, and Owner PAT settings writes.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.