Skip to content

[SCAL-323294] changes for fetch_data tool - #179

Open
saharsh-ts wants to merge 20 commits into
mainfrom
SCAL-323294_fetch-data
Open

[SCAL-323294] changes for fetch_data tool#179
saharsh-ts wants to merge 20 commits into
mainfrom
SCAL-323294_fetch-data

Conversation

@saharsh-ts

Copy link
Copy Markdown
Collaborator

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces two new tools, search_objects and fetch_data, to the MCP server for searching and retrieving data from ThoughtSpot objects (Answers and Liveboards). It includes new schemas, gRPC-backed API clients, terminology mapping for synonyms, and comprehensive unit tests. The reviewer identified a critical issue in src/servers/mcp-server.ts where the asynchronous validateConnection method is not awaited in the Ping tool case, causing the check to always evaluate to true.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/servers/mcp-server.ts Outdated
case ToolName.Ping: {
if (this.ctx.props.accessToken && this.ctx.props.instanceUrl) {
if (!this.getThoughtSpotService(recorder).validateConnection()) {
if (!this.getThoughtSpotService(recorder).validateConnection()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The validateConnection method is asynchronous and returns a Promise<boolean>. Since it is not awaited here, the condition !promise will always evaluate to false because any Promise object is truthy. This effectively bypasses the connection validation check. Please add await to correctly evaluate the promise result.

Suggested change
if (!this.getThoughtSpotService(recorder).validateConnection()) {
if (!(await this.getThoughtSpotService(recorder).validateConnection())) {
References
  1. When a method returns a Promise, ensure it is awaited to prevent race conditions and potential data loss, especially when subsequent operations depend on its completion.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added await

@saharsh-ts
saharsh-ts force-pushed the SCAL-323294_fetch-data branch from 2b7918b to de4930a Compare July 13, 2026 07:47
@mouryabalabhadra

Copy link
Copy Markdown
Collaborator

@copilot review the pr

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@copilot review the pr

Reviewed the PR and addressed one issue: fetch_data now rejects empty visualization_ids instead of treating it as “fetch all”. Added validation coverage in tests as well. Fixed in commit 352f265.

@saharsh-ts

Copy link
Copy Markdown
Collaborator Author

@copilot review the pr

@saharsh-ts
saharsh-ts force-pushed the SCAL-323294_fetch-data branch from 6454d11 to ddaf1fa Compare July 20, 2026 09:47
Comment thread src/servers/tool-definitions.ts Outdated
),
columns: z.array(z.string()).describe("The column names, in order."),
data_rows: z
.array(z.array(z.unknown()))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to add a proper type contract

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tightened to string | number | boolean | null datatypes.


// Round numeric cells to 2 decimals: collapses FP noise and trims payload.
// Non-numbers and non-finite values pass through untouched.
function roundCell(value: unknown): unknown {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems arbitrary, what if the customer wants more precision? I feel we should return the full value for now, and not prematurely optimize this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed — cells now returned at full precision.

// treats it as "must hold the whole viz" and 500s when it's too small.
// Start at maxRows; on that error, bump to the required count and refetch,
// then cap rows client-side below. Attempts are bounded (a full Liveboard
// can report a larger viz on each retry) to avoid a runaway loop.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a hacky design, we should make the API call such that it is successful on the first try. Is there no way to do that using this API?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked to one call — Answers pass record_size = max_rows,
Liveboards request the max 32-bit int.
Verified on local instance.

@saharsh-ts
saharsh-ts force-pushed the SCAL-323294_fetch-data branch from 349b5d8 to cb87e5c Compare July 22, 2026 08:45
@saharsh-ts

Copy link
Copy Markdown
Collaborator Author

@copilot review the PR

Comment thread src/servers/tool-definitions.ts Outdated
Comment thread src/servers/tool-definitions.ts Outdated
Comment thread src/servers/tool-definitions.ts Outdated
Comment thread src/servers/tool-definitions.ts Outdated
Comment thread src/thoughtspot/fetch-data/fetch-data.ts Outdated
Comment thread src/thoughtspot/fetch-data/fetch-data.ts Outdated
Comment thread src/servers/tool-definitions.ts Outdated
Comment thread src/servers/tool-definitions.ts
Comment thread src/thoughtspot/fetch-data/fetch-data.ts Outdated
@mouryabalabhadra

Copy link
Copy Markdown
Collaborator

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the get_object_data tool to fetch tabular data for saved Answers and Liveboards, gated by a new canDownloadData privilege check. It maps the REST v2 metadata endpoints, normalizes data formats, and includes comprehensive integration and unit tests. Feedback recommends improving type safety in the catch block of callGetObjectData by verifying if the error is an instance of Error before accessing its message, and refactoring the supported object types into a shared constant to eliminate duplication between the Zod schema and the local enum.

Comment thread src/servers/mcp-server.ts Outdated
Comment thread src/thoughtspot/get-object-data/get-object-data.ts Outdated
@saharsh-ts
saharsh-ts requested review from a team and mouryab as code owners August 22, 2026 08:38
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 22, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
rifdhan-test-app 376bd4b Aug 27 2026, 08:34 AM


// "Unbounded" record_size for Liveboards (they 500 if it can't hold the whole
// viz). Max 32-bit signed int — the endpoint reads it as a GraphQL Int.
export const LIVEBOARD_RECORD_SIZE = 2_147_483_647;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Liveboard fetches send record_size = 2,147,483,647 and apply max_rows only client-side, so the Worker downloads the entire result set of every visualization before slicing to 25 rows.

@saharsh-ts saharsh-ts Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack. The Liveboard /data endpoint 500s when record_size is below the viz's full row count, so it can't be bounded server-side — record_size is int32-max and max_rows caps client-side.

so we fetch complete liveboard vizzes, and then use min(numViz, 25) objects to explain the liveboard.

.optional()
.describe(
"Set only when this result is a specific visualization on a Liveboard: `object_id` is the Liveboard and this is the visualization. Pass it to fetch_data as `visualization_ids` to fetch just this viz.",
"Set only when this result is a specific visualization on a Liveboard: `object_id` is the Liveboard and this is the visualization. Pass it to get_object_data as `visualization_ids` to fetch just this viz.",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are unconditionally instructing the model to call get_object_data but it sbehind privilege

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment thread src/servers/mcp-server.ts Outdated
`Fetched data for ${object_id} (${result.data.length} result(s))`,
);
} catch (error) {
// Surface the upstream message (e.g. status 401/500) so the failure is

@mouryabalabhadra mouryabalabhadra Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is too generic catch all error. 401 errors have the dispatch-layer 401 handler to return explicit reauthentication message

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread src/servers/mcp-server.ts
}

@WithSpan("call-get-object-data")
async callGetObjectData(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callGetObjectData checks canDownloadData() but doesn't wait for ensureSessionInfo()

it should do similar to listTools

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added await this.ensureSessionInfo() before the gate, same as listTools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants