MCP Server type issue for single/multi select

Confirming this on our self-hosted instance — with additional detail on the root cause and a data-integrity angle that may not be in the thread yet.

Environment

  • Baserow self-hosted, version 2.2.2
  • Backend served via ASGI (Server: uvicorn confirmed in response headers)
  • PostgreSQL backend
  • Accessed through the built-in MCP server endpoint (/mcp//sse) via the mcp-remote stdio<->SSE bridge

Symptom

Every MCP write tool call (create_rows) returns:

Error: select_for_update cannot be used outside of a transaction.

MCP read tools (list_databases, list_tables, get_table_schema, list_table_rows) work fine. The identical write via the REST API (POST /api/database/rows/table/{id}/) also works fine. So the fault is specific to the MCP server’s write path.

Data-integrity angle (the important part)
Despite returning an error, the row is actually created and committed. The caller sees a failure, but a row appears in the table. A client that retries on error therefore produces duplicates — in our case 4 retries created 4 duplicate rows plus the
original. This isn’t just a feature outage; it’s silent partial-write + duplication.

Root cause analysis
select_for_update cannot be used outside of a transaction is Django’s TransactionManagementError, raised when QuerySet.select_for_update() runs with the DB connection in autocommit mode and no active transaction.atomic() block.

  • Baserow’s REST mutating endpoints execute inside a transaction (ATOMIC_REQUESTS / explicit atomic()), so the row-creation logic — which internally uses select_for_update to lock rows for order computation and link-field integrity — works correctly.
  • The built-in MCP server’s write tools dispatch into the same RowHandler code, but the MCP tool-handler path is not wrapped in transaction.atomic(). Under autocommit, the internal select_for_update raises immediately.
  • Because there is no surrounding transaction, the work completed before the failing select_for_update (the row INSERT, and link/m2m writes) is auto-committed and never rolled back → error returned to the client and an orphan row left behind.

Workaround
Use the REST API with a Database token for writes; the MCP endpoint remains usable for reads.