Skip to content

Commit 80b7488

Browse files
Fix(tools/bigquery-conversational-analytics): fix authentication scope error in Cloud Run (googleapis#1381)
## Problem Fixes googleapis#1378 - BigQuery Conversational Analytics tool fails with `ACCESS_TOKEN_SCOPE_INSUFFICIENT` error in Cloud Run environments while other BigQuery tools work fine. ## Root Cause The conversational analytics tool was using `BigQueryTokenSource()` with limited `bigqueryapi.Scope`, but the Gemini Data Analytics API (`geminidataanalytics.googleapis.com`) requires broader `cloud-platform` scope. ## Solution - Replace ADC token acquisition to use `google.DefaultTokenSource` with `cloud-platform` scope - Remove dependency on limited BigQuery scope from source - Maintain compatibility with existing OAuth flow ## Testing - ✅ **Local testing confirmed**: Tool now works perfectly - ✅ **Test script**: https://github.com/johanesalxd/bq-agent-app/blob/main/setup/mcp_toolbox_ca_issue/test_detailed_error.py - ✅ **Successful response**: Returns proper schema information and conversational answers - ✅ **All BigQuery tool tests pass**: No regression in other tools - ✅ **Build successful**: No compilation errors ## Impact - **Fixes**: Cloud Run deployment authentication errors - **Maintains**: Local development functionality - **Preserves**: All existing BigQuery tool functionality --------- Co-authored-by: Huan Chen <142538604+Genesis929@users.noreply.github.com>
1 parent 874ee0c commit 80b7488

2 files changed

Lines changed: 20 additions & 5 deletions

File tree

internal/sources/bigquery/bigquery.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ func (s *Source) BigQueryTokenSource() oauth2.TokenSource {
188188
return s.TokenSource
189189
}
190190

191+
func (s *Source) BigQueryTokenSourceWithScope(ctx context.Context, scope string) (oauth2.TokenSource, error) {
192+
return google.DefaultTokenSource(ctx, scope)
193+
}
194+
191195
func (s *Source) GetMaxQueryResultRows() int {
192196
return s.MaxQueryResultRows
193197
}

internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T
5454

5555
type compatibleSource interface {
5656
BigQueryClient() *bigqueryapi.Client
57-
BigQueryTokenSource() oauth2.TokenSource
57+
BigQueryTokenSourceWithScope(ctx context.Context, scope string) (oauth2.TokenSource, error)
5858
BigQueryProject() string
5959
BigQueryLocation() string
6060
GetMaxQueryResultRows() int
@@ -145,6 +145,17 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
145145
InputSchema: parameters.McpManifest(),
146146
}
147147

148+
// Get cloud-platform token source for Gemini Data Analytics API during initialization
149+
var bigQueryTokenSourceWithScope oauth2.TokenSource
150+
if !s.UseClientAuthorization() {
151+
ctx := context.Background()
152+
ts, err := s.BigQueryTokenSourceWithScope(ctx, "https://www.googleapis.com/auth/cloud-platform")
153+
if err != nil {
154+
return nil, fmt.Errorf("failed to get cloud-platform token source: %w", err)
155+
}
156+
bigQueryTokenSourceWithScope = ts
157+
}
158+
148159
// finish tool setup
149160
t := Tool{
150161
Name: cfg.Name,
@@ -155,7 +166,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
155166
AuthRequired: cfg.AuthRequired,
156167
Client: s.BigQueryClient(),
157168
UseClientOAuth: s.UseClientAuthorization(),
158-
TokenSource: s.BigQueryTokenSource(),
169+
TokenSource: bigQueryTokenSourceWithScope,
159170
manifest: tools.Manifest{Description: cfg.Description, Parameters: parameters.Manifest(), AuthRequired: cfg.AuthRequired},
160171
mcpManifest: mcpManifest,
161172
MaxQueryResultRows: s.GetMaxQueryResultRows(),
@@ -197,13 +208,13 @@ func (t Tool) Invoke(ctx context.Context, params tools.ParamValues, accessToken
197208
return nil, fmt.Errorf("error parsing access token: %w", err)
198209
}
199210
} else {
200-
// Use ADC
211+
// Use cloud-platform token source for Gemini Data Analytics API
201212
if t.TokenSource == nil {
202-
return nil, fmt.Errorf("ADC is missing a valid token source")
213+
return nil, fmt.Errorf("cloud-platform token source is missing")
203214
}
204215
token, err := t.TokenSource.Token()
205216
if err != nil {
206-
return nil, fmt.Errorf("failed to get token from ADC: %w", err)
217+
return nil, fmt.Errorf("failed to get token from cloud-platform token source: %w", err)
207218
}
208219
tokenStr = token.AccessToken
209220
}

0 commit comments

Comments
 (0)