Description
When the bigquery-execute-sql tool receives a user/query validation error from BigQuery during the dry-run phase, it currently wraps that error as a ClientServerError with http.StatusInternalServerError.
That classification causes the MCP layer to return a JSON-RPC internal error and an HTTP 500 instead of a normal tool error result. In practice, this makes LLM clients treat normal BigQuery SQL mistakes as transport failures.
Repro
In our sandbox, this showed up when an MCP client called execute_sql with invalid-but-common BigQuery SQL such as:
SELECT *
FROM `project.dataset.table`
WHERE created_at >= DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH)
against a TIMESTAMP column, or with DATE_TRUNC(timestamp_col, WEEK) instead of TIMESTAMP_TRUNC(...).
BigQuery correctly returns a 400-series query validation error like invalidQuery / No matching signature ..., but the toolbox currently turns that into an MCP HTTP 500.
Root cause
internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go currently does:
if err != nil {
return nil, util.NewClientServerError("query validation failed", http.StatusInternalServerError, err)
}
The similar bigquery-sql tool already uses util.ProcessGcpError(err) instead, which preserves auth failures as transport errors but treats normal GCP request/query failures as agent/tool errors.
Expected behavior
For invalid BigQuery SQL submitted through MCP:
- the toolbox should not emit HTTP 500
- the MCP response should be a normal tool result with
isError: true
- the BigQuery error message should stay visible to the client so the model/user can correct the query
Proposed fix
Use util.ProcessGcpError(err) in bigquery-execute-sql for dry-run validation failures, matching the existing bigquery-sql path.
I have a small PR ready with that change plus a focused regression test for the GCP error classifier.
Description
When the
bigquery-execute-sqltool receives a user/query validation error from BigQuery during the dry-run phase, it currently wraps that error as aClientServerErrorwithhttp.StatusInternalServerError.That classification causes the MCP layer to return a JSON-RPC internal error and an HTTP 500 instead of a normal tool error result. In practice, this makes LLM clients treat normal BigQuery SQL mistakes as transport failures.
Repro
In our sandbox, this showed up when an MCP client called
execute_sqlwith invalid-but-common BigQuery SQL such as:against a
TIMESTAMPcolumn, or withDATE_TRUNC(timestamp_col, WEEK)instead ofTIMESTAMP_TRUNC(...).BigQuery correctly returns a 400-series query validation error like
invalidQuery/No matching signature ..., but the toolbox currently turns that into an MCP HTTP 500.Root cause
internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.gocurrently does:The similar
bigquery-sqltool already usesutil.ProcessGcpError(err)instead, which preserves auth failures as transport errors but treats normal GCP request/query failures as agent/tool errors.Expected behavior
For invalid BigQuery SQL submitted through MCP:
isError: trueProposed fix
Use
util.ProcessGcpError(err)inbigquery-execute-sqlfor dry-run validation failures, matching the existingbigquery-sqlpath.I have a small PR ready with that change plus a focused regression test for the GCP error classifier.