@@ -25,86 +25,88 @@ interface Context {
2525 props : Props ;
2626}
2727
28- export function createMCPServer ( ctx : Context ) : Server {
29- const server = new Server ( {
30- name : "ThoughtSpot" ,
31- version : "1.0.0" ,
32- capabilities : {
33- tools : { } ,
34- logging : { } ,
35- completion : { } ,
36- resources : { } ,
37- }
38- } ) ;
39-
40- server . setRequestHandler ( ListToolsRequestSchema , async ( ) => {
41- return {
42- tools : [
43- {
44- name : ToolName . Ping ,
45- description : "Simple ping tool to test connectivity and Auth" ,
46- inputSchema : zodToJsonSchema ( PingSchema ) as ToolInput ,
47- } ,
48- {
49- name : ToolName . GetRelevantData ,
50- description : "Get relevant data from ThoughtSpot database" ,
51- inputSchema : zodToJsonSchema ( GetRelevantDataSchema ) as ToolInput ,
52- }
53- ]
54- } ;
55- } ) ;
56-
57- // Handle call tool request
58- server . setRequestHandler ( CallToolRequestSchema , async ( request : z . infer < typeof CallToolRequestSchema > ) => {
59- const { name } = request . params ;
60-
61- switch ( name ) {
62- case ToolName . Ping :
63- if ( ctx . props . accessToken && ctx . props . instanceUrl ) {
64- return {
65- content : [ { type : "text" , text : "Pong" } ] ,
66- } ;
67- } else {
68- return {
69- content : [ { type : "text" , text : "ERROR: Not authenticated" } ] ,
70- } ;
28+ export class MCPServer extends Server {
29+ constructor ( private ctx : Context ) {
30+ super ( {
31+ name : "ThoughtSpot" ,
32+ version : "1.0.0" ,
33+ capabilities : {
34+ tools : { } ,
35+ logging : { } ,
36+ completion : { } ,
37+ resources : { } ,
38+ }
39+ } ) ;
40+ }
41+
42+ async init ( ) {
43+ this . setRequestHandler ( ListToolsRequestSchema , async ( ) => {
44+ return {
45+ tools : [
46+ {
47+ name : ToolName . Ping ,
48+ description : "Simple ping tool to test connectivity and Auth" ,
49+ inputSchema : zodToJsonSchema ( PingSchema ) as ToolInput ,
50+ } ,
51+ {
52+ name : ToolName . GetRelevantData ,
53+ description : "Get relevant data from ThoughtSpot database" ,
54+ inputSchema : zodToJsonSchema ( GetRelevantDataSchema ) as ToolInput ,
55+ }
56+ ]
57+ } ;
58+ } ) ;
59+
60+ // Handle call tool request
61+ this . setRequestHandler ( CallToolRequestSchema , async ( request : z . infer < typeof CallToolRequestSchema > ) => {
62+ const { name } = request . params ;
63+
64+ switch ( name ) {
65+ case ToolName . Ping :
66+ if ( this . ctx . props . accessToken && this . ctx . props . instanceUrl ) {
67+ return {
68+ content : [ { type : "text" , text : "Pong" } ] ,
69+ } ;
70+ } else {
71+ return {
72+ content : [ { type : "text" , text : "ERROR: Not authenticated" } ] ,
73+ } ;
74+ }
75+
76+ case ToolName . GetRelevantData : {
77+ return this . callGetRelevantData ( request ) ;
7178 }
7279
73- case ToolName . GetRelevantData : {
74- return callGetRelevantData ( request , server , ctx ) ;
80+ default :
81+ throw new Error ( `Unknown tool: ${ name } ` ) ;
7582 }
83+ } ) ;
84+ }
85+
86+ async callGetRelevantData ( request : z . infer < typeof CallToolRequestSchema > ) {
87+ const { query } = GetRelevantDataSchema . parse ( request . params . arguments ) ;
88+ const client = getThoughtSpotClient ( this . ctx . props . instanceUrl , this . ctx . props . accessToken ) ;
89+ const progressToken = request . params . _meta ?. progressToken ;
90+ let progress = 0 ;
91+
92+ const relevantData = await getRelevantData ( query , false , ( data ) => this . notification ( {
93+ method : "notifications/progress" ,
94+ params : {
95+ message : data ,
96+ progressToken : progressToken ,
97+ progress : Math . max ( progress ++ * 10 , 100 ) ,
98+ total : 100 ,
99+ } ,
100+ } ) , client ) ;
76101
77- default :
78- throw new Error ( `Unknown tool: ${ name } ` ) ;
79- }
80- } ) ;
81-
82- return server ;
102+ return {
103+ content : [ {
104+ type : "text" ,
105+ text : relevantData . allAnswers . map ( ( answer ) => `Question: ${ answer . question } \nAnswer: ${ answer . data } ` ) . join ( "\n\n" )
106+ } , {
107+ type : "text" ,
108+ text : `Dashboard Url: ${ relevantData . liveboard } ` ,
109+ } ] ,
110+ } ;
111+ }
83112}
84-
85- async function callGetRelevantData ( request : z . infer < typeof CallToolRequestSchema > , server : Server , ctx : Context ) {
86- const { query } = GetRelevantDataSchema . parse ( request . params . arguments ) ;
87- const client = getThoughtSpotClient ( ctx . props . instanceUrl , ctx . props . accessToken ) ;
88- const progressToken = request . params . _meta ?. progressToken ;
89- let progress = 0 ;
90-
91- const relevantData = await getRelevantData ( query , false , ( data ) => server . notification ( {
92- method : "notifications/progress" ,
93- params : {
94- message : data ,
95- progressToken : progressToken ,
96- progress : Math . max ( progress ++ * 10 , 100 ) ,
97- total : 100 ,
98- } ,
99- } ) , client ) ;
100-
101- return {
102- content : [ {
103- type : "text" ,
104- text : relevantData . allAnswers . map ( ( answer ) => `Question: ${ answer . question } \nAnswer: ${ answer . data } ` ) . join ( "\n\n" )
105- } , {
106- type : "text" ,
107- text : `Dashboard Url: ${ relevantData . liveboard } ` ,
108- } ] ,
109- } ;
110- }
0 commit comments