Repository navigation
Add MCP tools to delete database tables, team databases, shared library entries and git tokens - #8857
Conversation
…ry entries and git tokens
… disabled git integration on token delete
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8857 +/- ##
==========================================
+ Coverage 79.01% 79.05% +0.03%
==========================================
Files 475 476 +1
Lines 25820 25863 +43
Branches 6867 6875 +8
==========================================
+ Hits 20402 20445 +43
Misses 5418 5418
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| }, | ||
| handler: async (args, { inject }) => { | ||
| const segments = args.path.split('/') | ||
| if (segments.some(segment => segment === '' || segment === '.' || segment === '..')) { |
There was a problem hiding this comment.
A folder delete goes through byPath, which matches with an unescaped LIKE '<path>%', so deleting my_utils also wipes myXutils/... 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.
| CAUTION: flows and snippets that other members of the team load from the library are gone for everyone. Confirm with the user before calling this, naming the entry or the folder. | ||
| Entries of different types can share a path. Pass type to delete only the entry of that type; without it one of the entries at that path is deleted, and which one is not defined. A folder delete without type covers all types. | ||
| Replies { status: "okay", deleteCount } with the number of entries removed. A path that matches nothing returns 404, so repeating a call is harmless; the 404 is the same when the shared library is not enabled for the team, the team does not exist, or the caller is not a member of it.`, | ||
| annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }, |
There was a problem hiding this comment.
idempotentHint: true (and "repeating a call is harmless") doesn't hold for folder deletes: a retry deletes anything added under that path since the first call. Exact entry deletes are fine. Probably worth dropping the hint on this one, or at least scoping the wording to single entries.
There was a problem hiding this comment.
Agreed. I dropped idempotentHint and the "harmless" wording. The description now says a repeated folder delete also removes anything added under the folder since the first call.
| if (response.statusCode >= 400) { | ||
| return response | ||
| } | ||
| return { statusCode: response.statusCode, json: () => ({ status: 'okay' }) } |
There was a problem hiding this comment.
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.
…es, in-use git tokens and literal library paths
…repeated folder delete removes newer entries
…lete-tools # Conflicts: # forge/ee/lib/mcp/tools/library.js # forge/ee/lib/mcp/tools/teams.js # test/unit/forge/ee/lib/mcp/tools/library_spec.js # test/unit/forge/ee/lib/mcp/tools/teams_spec.js
Closes #7710
Adds the four delete tools for team data, all annotated
destructiveHint: trueso they are served as destructive tools:platform_delete_database_table,platform_delete_team_database,platform_delete_library_entry(newlibrary.js) andplatform_delete_git_token(inteams.js, next toplatform_list_team_git_tokens). Each description states what is lost and what else breaks, so the caller can confirm with the user first. Every tool replies{ status: "okay" }on success, except the library one which passes the route reply through,{ status, deleteCount }. Error responses are passed through unchanged.Things I checked against the real routes:
DELETE .../tables/:tableNametakes the schema as an optional trailing path segment, not a query parameter.schemaNameis required, as in the get and query table tools, so the tool always deletes the table in the given schema. An empty or dot table or schema name drops out of the URL and would delete the table from whichever schema it is in, so the tool rejects those.{ status: "okay" }throughemptySuccessAsOkay. The database and git token routes reply{}, which is mapped to the same shape.idempotentHint: true./storage/library/:libraryId/*, with no/api/v1prefix as the issue lists it. The tool takesteamId, since the library id is the team hashid.typeonly narrows the match, and without it one arbitrary entry is removed when several types share a path..and..segments and encodes each segment. The URL resolves.and..segments, even encoded ones, before the route sees the path, so without this checka/../bwould deleteb.token_in_usenaming the pipelines, which the description explains.../teams/<id>would reach another route.Issues found while testing, fixed in the routes:
_and%acted as wildcards. Fixed in Match shared library folders literally and reject an empty delete path #8878.Merge after #8878 and #8880.