diff --git a/src/servers/mcp-server.ts b/src/servers/mcp-server.ts index b4b4886..54b3b88 100644 --- a/src/servers/mcp-server.ts +++ b/src/servers/mcp-server.ts @@ -3,6 +3,7 @@ import type { ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import { SpanStatusCode, context, trace } from "@opentelemetry/api"; +import type { AgentConversation } from "@thoughtspot/rest-api-sdk"; import type { z } from "zod"; import { TrackEvent } from "../metrics"; import type { ApiVersionMode } from "../metrics/runtime/metric-types"; @@ -381,10 +382,22 @@ Provide this url to the user as a link to view the liveboard in ThoughtSpot.`; ); span?.setAttribute("data_source_id", data_source_id ?? "(none)"); - const response = - await this.getThoughtSpotService(recorder).createAgentConversation( - data_source_id, + let response: AgentConversation; + try { + response = + await this.getThoughtSpotService(recorder).createAgentConversation( + data_source_id, + ); + } catch (error) { + if (!(error as any)?.message?.includes("failed with status 401")) { + throw error; + } + + return this.createErrorResponse( + "Your authentication has expired, please reauthenticate and try again. You may need to disconnect and reconnect the MCP Server if you don't have any other way to reauthenticate.", + "User authentication has expired, prompting them to reauthenticate", ); + } recorder.setAnalyticsContext({ analyticalSessionId: response.conversation_id, }); diff --git a/test/servers/mcp-server.spec.ts b/test/servers/mcp-server.spec.ts index 1eb50d7..32cbe54 100644 --- a/test/servers/mcp-server.spec.ts +++ b/test/servers/mcp-server.spec.ts @@ -1278,6 +1278,50 @@ describe("MCP Server", () => { }), ).rejects.toThrow("Failed to create conversation"); }); + + it("should return auth-expired error response when service throws 401 error", async () => { + vi.spyOn(thoughtspotClient, "getThoughtSpotClient").mockReturnValue({ + getSessionInfo: vi.fn().mockResolvedValue({ + clusterId: "test-cluster-123", + clusterName: "test-cluster", + releaseVersion: "10.13.0.cl-110", + userGUID: "test-user-123", + configInfo: { + mixpanelConfig: { + devSdkKey: "test-dev-token", + prodSdkKey: "test-prod-token", + production: false, + }, + selfClusterName: "test-cluster", + selfClusterId: "test-cluster-123", + enableSpotterDataSourceDiscovery: true, + }, + userName: "test-user", + currentOrgId: "test-org", + privileges: [], + }), + createAgentConversationWithAutoMode: vi + .fn() + .mockRejectedValue( + new Error( + "createAgentConversationWithAutoMode failed with status 401", + ), + ), + instanceUrl: "https://test.thoughtspot.cloud", + } as any); + + await server.init(); + + const result = await server.callCreateAnalysisSession({ + method: "tools/call", + params: { name: "create_analysis_session", arguments: {} }, + }); + + expect(result.isError).toBe(true); + expect((result.content[0] as any).text).toContain( + "Your authentication has expired", + ); + }); }); describe("Caching", () => {