Repository navigation
feat: add update_rows and delete_rows tools - #40
Conversation
dc805c8 to
1f3d607
Compare
|
Should
Worth noting for any future revisit: Not blocking — the mandatory- |
Register row-mutation tools under the existing CRDB_MCP_ENABLE_WRITE_QUERIES gate, matching the single read-only/write switch used by other database MCP servers. Both tools parse via cockroachdb-parser, accept exactly one statement, require a WHERE clause, and block DML hidden in CTEs, joined table expressions (UPDATE ... FROM, DELETE ... USING), or expression subqueries. Both carry a destructiveHint annotation, and delete_rows an idempotentHint, so MCP clients can surface accurate prompts. RETURNING is now supported across all three DML tools: statements with a RETURNING clause route through Query instead of Exec so the returned rows reach the agent (Exec silently drops them). This matters most for DELETE, where the removed rows cannot be read back afterwards.
1f3d607 to
271fed2
Compare
Thanks for the review @arjunmahishi! Fair point, the single flag is intentional. I have added a note in the README (Tools section) making the RBAC path explicit, so the single-flag plus RBAC split is documented. |
Adds update_rows and delete_rows tools so agents can modify and remove existing rows, completing the DML surface alongside
insert_rows.Design
Follows the ecosystem pattern (MongoDB MCP, Postgres MCP both gate all writes behind a single read-only/write switch): both tools register under the existing
CRDB_MCP_ENABLE_WRITE_QUERIES=truegate. No new env vars.Guardrails, all knob-free:
parseSingleStatementpath asinsert_rows).UPDATE/DELETEis rejected before reaching the database.UPDATE ... FROM,DELETE ... USING), or expression subquery are rejected via a sharedensureNoHiddenDMLhelper; read-only ones pass.destructiveHint: trueon both tools, plusidempotentHint: trueondelete_rows, so MCP clients can surface accurate prompts.RETURNING
Supported across all three DML tools (
insert_rowsincluded): a statement with aRETURNINGclause routes through Query instead of Exec so the returned rows reach the agent, which Exec otherwise drops. Matters most forDELETE, where the removed rows cannot be read back afterwards.Testing
insert_rows_test.go: wrong statement type, missing WHERE, multi-statement, CTE-hidden DML, and bracket-subquery DML in WHERE / FROM / USING; plus valid execution, RETURNING-through-Query, and legitimate SELECT subqueries in SET/WHERE.go test ./...passes.