FlowFuse / FlowFuse/flowfuse

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

Open
#7,712 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:** #7682 (5.13 Broker and MQTT (special review))
**Tool file:** new `forge/ee/lib/mcp/tools/broker.js`

`readOnlyHint: false`, `destructiveHint: false`. **Contingent on a product decision to allow broker mutation over MCP.** None of these mint credentials, so #7513 does not block them. Sibling broker lifecycle transitions are consolidated into a single action tool; topic create/update touch broker state but not credentials.

| Tool | Endpoint(s) | Scope | Annotation |
|---|---|---|---|
| `platform_broker_lifecycle_action` (`action`: `start`\|`stop`\|`suspend`) | broker lifecycle routes | `broker:credentials:edit` | write |
| `platform_create_broker_topic` | `POST /teams/:teamId/brokers/:brokerId/topics` | `broker:topics:write` | write |
| `platform_update_broker_topic` | `PUT /teams/:teamId/brokers/:brokerId/topics/:topicId` | `broker:topics:write` | write |

**Design notes:**
- Only the topic **create** route (`POST /topics`) is dual-gated (agent/broker token scope OR user `broker:topics:write`). The **update** route (`PUT /topics/:topicId`) uses a plain `needsPermission('broker:topics:write')` and is not dual-gated; its path is a single `:topicId` param, not a wildcard. The handler only updates `metadata`.
- Broker lifecycle (`start`/`stop`/`suspend`) maps to `PUT /brokers/:brokerId/start|stop|suspend`; it touches broker state but does not mint credentials, so it is not in the #7513 class; it remains contingent on the broker-mutation decision.
- The whole surface is gated by the enterprise license tier and the per-team `teamBroker` feature flag.

**Tool definitions (description + zod inputSchema):**
```js
platform_broker_lifecycle_action: {
description: 'Applies a lifecycle transition (start, stop, or suspend) to the broker agent.',
inputSchema: z.object({
teamId: z.string().describe('team hashid'),
brokerId: z.string().describe("broker id: either the literal 'team-broker' or a 3rd-party broker hashid"),
action: z.enum(['start', 'stop', 'suspend']).describe('lifecycle transition to apply to the broker agent')
})
},
platform_create_broker_topic: {
description: 'Creates one or more topics for a broker. Accepts a single topic object instead of an array.',
inputSchema: z.object({
teamId: z.string().describe('team hashid'),
brokerId: z.string().describe("broker id: either the literal 'team-broker' or a 3rd-party broker hashid"),
topics: z.array(z.object({
topic: z.string().describe('MQTT topic string'),
type: z.any().optional().describe('inferred payload schema/type; stored as inferredSchema'),
metadata: z.record(z.any()).optional().describe('arbitrary topic metadata (e.g. description, schema)')
})).describe('Topics to store')
})
},
platform_update_broker_topic: {
description: 'Updates a broker topic. Only the topic metadata is updated.',
inputSchema: z.object({
teamId: z.string().describe('team hashid'),
brokerId: z.string().describe("broker id: either the literal 'team-broker' or a 3rd-party broker hashid"),
topicId: z.string().describe('topic hashid'),
metadata: z.record(z.any()).describe('replacement topic metadata')
})
}
```

**Tests (only if writes approved):**
- The action tool routes each enum value to the correct lifecycle route.
- Read-only PAT rejected for every tool here.
- Feature-disabled team returns the descriptive gate error.

---

Contributor guide

Open the contributing guide

Research direction

Start with the product decision in parent issue #7682, then inspect forge/ee/lib/mcp/tools/broker.js and the listed broker lifecycle and topic endpoints. Verify the enterprise license and teamBroker gates, then add the specified tools only if writes are approved. Run tests covering lifecycle routing, read-only PAT rejection, and the feature-disabled error.

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
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.