Skip to content

Commit c74367c

Browse files
committed
refactor to class
1 parent b97b427 commit c74367c

File tree

2 files changed

+85
-81
lines changed

2 files changed

+85
-81
lines changed

src/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import OAuthProvider from "@cloudflare/workers-oauth-provider";
22
import { McpAgent } from "agents/mcp";
33
import handler from "./handlers";
44
import { Props } from "./utils";
5-
import { createMCPServer } from "./mcp-server";
5+
import { MCPServer } from "./mcp-server";
66

77

88
export class ThoughtSpotMCP extends McpAgent<Env, any, Props> {
9-
server = createMCPServer(this);
9+
server = new MCPServer(this);
1010

11-
async init() { }
11+
async init() {
12+
await this.server.init();
13+
}
1214
}
1315

1416
export default new OAuthProvider({

src/mcp-server.ts

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)