5.1-c Delete and destructive tools (phase 2)
- Dominant language
- JavaScript
- Stars
- 400
- Forks
- 89
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 149
Description
**Parent:** #7670 (5.1 Instance lifecycle and actions)
**Tool file:** `forge/ee/lib/mcp/tools/instances.js` (extend), `forge/ee/lib/mcp/tools/devices.js` (extend)
`destructiveHint: true`. Kept separate from ordinary writes so MCP clients gate them behind confirmation by default. Rollback lives here because it overwrites the running flows even though it is not a delete.
| Tool | Endpoint | Scope | Annotation |
|---|---|---|---|
| `platform_delete_instance` (`instanceType`: `hosted`\|`remote`) | hosted: `DELETE /projects/:id`; remote: `DELETE /devices/:id` | `project:delete` (hosted), `device:delete` (remote) | destructive |
| `platform_rollback_hosted_instance` | `POST /projects/:id/actions/rollback` | `project:snapshot:rollback` | destructive |
**Consolidation notes:**
- `platform_delete_instance` covers both hosted and remote instances through an `instanceType` discriminator, mirroring the read tools. It routes to `DELETE /projects/:id` (`project:delete`) or `DELETE /devices/:id` (`device:delete`) based on `instanceType`.
**Design notes:** rollback validates that the snapshot belongs to the instance; surface the validation error descriptively.
**Tool definitions (description + zod inputSchema):**
```js
platform_delete_instance: {
description: 'Permanently deletes an instance. instanceType selects whether instanceId is a hosted instance UUID or a remote instance (device) hashid.',
inputSchema: z.object({
instanceId: z.string().describe('Instance id: hosted instance UUID, or remote instance (device) hashid'),
instanceType: z.enum(['hosted', 'remote']).describe('Whether instanceId refers to a hosted instance or a remote instance (device)')
})
}
platform_rollback_hosted_instance: {
description: 'Rolls a hosted instance back to a snapshot, overwriting the running flows. The snapshot is validated to belong to the instance.',
inputSchema: z.object({
instanceId: z.string().uuid().describe('UUID of the hosted instance to roll back'),
snapshot: z.string().describe('Opaque hashid of the snapshot to roll back to')
})
}
```
**Tests:** every tool carries `destructiveHint: true`; read-only PAT rejected; `platform_delete_instance` routes by `instanceType`; rollback with a foreign snapshot returns the descriptive error.
---
Contributor guide
Research direction
Start by reading forge/ee/lib/mcp/tools/instances.js and forge/ee/lib/mcp/tools/devices.js, especially the existing read tools and their authentication checks. Add the two destructive tools with the specified schemas, routes, scopes, annotations, and rollback validation, then run the MCP tool tests covering destructive hints, PAT rejection, instanceType routing, and foreign snapshots.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api, backend, security
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100