Repository navigation
Add MCP tools to delete database tables, team databases, shared library entries and git tokens #8857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add MCP tools to delete database tables, team databases, shared library entries and git tokens #8857
Changes from all commits
3afacd8
350d5f2
c1c94d8
4d5f190
2857024
7e67d65
31df57d
1a653a2
0bf7e15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| const { z } = require('zod') | ||
|
|
||
| const { toolError } = require('../schemas') | ||
| const { | ||
| teamIdSchema, | ||
| databaseIdSchema, | ||
|
|
@@ -9,7 +10,7 @@ const { | |
| countSchema, | ||
| recordSchema | ||
| } = require('../tool-schemas/tables') | ||
| const { redactDatabaseCredentials } = require('../utils') | ||
| const { redactDatabaseCredentials, emptySuccessAsOkay } = require('../utils') | ||
|
|
||
| module.exports = [ | ||
| { | ||
|
|
@@ -231,5 +232,52 @@ module.exports = [ | |
| json: () => ({ table: { name: args.name, schema: args.schema || 'public' } }) | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| name: 'platform_delete_database_table', | ||
| title: 'Delete Database Table', | ||
| description: `FlowFuse platform automation tool: | ||
| Permanently deletes a table from a FlowFuse Tables database, including every row it holds. This cannot be undone and there is no backup to restore from. | ||
| CAUTION: any flow that reads or writes the table will start failing as soon as it is gone. Confirm with the user before calling this, and use platform_get_database_table and platform_query_database_table_data first so you can tell them what is being lost. | ||
| Only the table in the given schema is deleted; a table with the same name in another schema is left alone. Team owners only. | ||
| Replies { status: "okay" } on success; a table or database that does not exist returns 404, so repeating a call is harmless. A 404 can also mean FlowFuse Tables is not available to the team.`, | ||
| annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }, | ||
| inputSchema: { | ||
| teamId: teamIdSchema, | ||
| databaseId: databaseIdSchema, | ||
| tableName: tableNameSchema, | ||
| schemaName: schemaNameSchema | ||
| }, | ||
| handler: async (args, { inject }) => { | ||
| // An empty or dot segment drops out of the URL, which would delete the table from any schema | ||
| if ([args.tableName, args.schemaName].some(segment => segment === '' || segment === '.' || segment === '..')) { | ||
| return toolError(400, 'invalid_request', 'tableName and schemaName must not be empty, "." or ".."') | ||
| } | ||
| const url = `/api/v1/teams/${args.teamId}/databases/${args.databaseId}/tables/${encodeURIComponent(args.tableName)}/${encodeURIComponent(args.schemaName)}` | ||
| const response = await inject({ method: 'DELETE', url }) | ||
| return emptySuccessAsOkay(response) | ||
| } | ||
| }, | ||
| { | ||
| name: 'platform_delete_team_database', | ||
| title: 'Delete Team Database', | ||
| description: `FlowFuse platform automation tool: | ||
| Permanently deletes a team's FlowFuse Tables database: every table in every schema, all of their rows, and the database login. This cannot be undone and there is no backup to restore from. | ||
| CAUTION: every flow and device in the team that uses the database will start failing, and the team is left with no database until a new one is created. Confirm with the user before calling this, and list what is in it first with platform_list_database_tables so you can tell them what will be lost. | ||
| The database does not need to be empty. Team owners only. | ||
| Replies { status: "okay" } on success; a database that does not exist returns 404, so repeating a call is harmless. A 404 can also mean FlowFuse Tables is not available to the team. | ||
| The delete fails with 500 while a client is still connected to the database, for example a running flow, and the database is kept. Retrying once nothing is connected finishes the delete.`, | ||
| annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }, | ||
| inputSchema: { | ||
| teamId: teamIdSchema, | ||
| databaseId: databaseIdSchema | ||
| }, | ||
| handler: async (args, { inject }) => { | ||
| const response = await inject({ method: 'DELETE', url: `/api/v1/teams/${args.teamId}/databases/${args.databaseId}` }) | ||
| if (response.statusCode >= 400) { | ||
| return response | ||
| } | ||
| return { statusCode: response.statusCode, json: () => ({ status: 'okay' }) } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of #8849 the route can answer 200 even when the drop failed, so this okay (and the description saying a repeat gives 404) tells the agent the data is gone when it might not be. Can't fix that here, but maybe a line in the description pointing at #8849 so the agent doesn't promise the user more than we know.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
| } | ||
| ] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A folder delete goes through
byPath, which matches with an unescapedLIKE '<path>%', so deletingmy_utilsalso wipesmyXutils/...for the whole team, with no undo. The description warns about it but the call still goes through. Until #8848 lands, might be worth just refusing folder paths with_or%here, it's one line and it takes the data loss off the table.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fixed in the route by #8878, which matches folder paths literally. I removed the warning from the description, and this merges after #8878.