MCP server: tool errors return isError false

Are you using our SaaS platform (Baserow.io) or self-hosting Baserow?

Self-hosted

If you are self-hosting, what version of Baserow are you running?

2.3.3

If you are self-hosting, which installation method do you use to run Baserow?

Docker version 29.7.2, build a7dcaa6
Docker Compose version v5.4.0

What are the exact steps to reproduce this issue?

I call the MCP endpoint directly over SSE, not through a desktop client, so I see the raw result payload. serverInfo reports {“name”: “Baserow MCP”, “version”: “1.28.1”}.

Setup: a table with a Number field (default, precision 0) and a Single select field with options ALPHA and BETA.

  1. update_rows {“Number”: “abc”} → refused, cause named. isError: false.
  2. update_rows {“Single select”: “GAMMA”} → refused, cause named. isError: false.
  3. delete_rows row_ids [1, 999999] → refused, nothing deleted (checked in the database). isError: false, and the text is just “Error:” with no message.

In all three the refusal is correct; only the flag is wrong, and case 3 has no message either.

The MCP spec says tool execution errors should carry isError: true so clients and models can detect the failure. Here a client reading the flag records a success while nothing was written. Looks like a bug rather than a design choice, but I’d rather ask: known issue, or is the flag left false on purpose?

Hello @Gatrio

Thanks for reporting.

It is a bug and we have fix for it in MCP server tool errors return isError: false instead of true · Issue #5961 · baserow/baserow · GitHub

Hi @Przemek , thanks for the feedback.
and thanks for #5963. I read the patch; a couple of notes and one question.

Scope, confirmed from the diff, so you don’t have to check: the three cases in my original post all go through the generic except Exception handler, so the flag fix covers all three. Good.

One thing the patch does not cover, and it may be worth folding in while the PR is open. The generic handler still returns f"Error: {e}". When the exception’s string representation is empty, the client receives Error: followed by nothing — no cause, no code, no offending row id. That is exactly what I measured on the mixed batch delete: not a flag problem, a message problem, and it survives #5963. The call becomes correctly flagged but stays undiagnosable.

A one-line fallback in the same path would close it — something like f"Error: {e or type(e).__name__}". Same handler, same PR, no extra surface. Your call entirely, but it seemed worth raising now rather than as a second issue later.

Question: #5963 targets develop. Is there a target release, even approximate — and will it land on the 2.3 line, or only on the next minor? I only re-verify against a released version.

Happy to re-run all three cases and report back once a release carrying it is out.