Skip to content

Commit 89b035b

Browse files
authored
Merge pull request #103 from ruturaj-browserstack/tools-re-factor
Feat : Added Tools in sdk context
2 parents 76f5910 + 4ccafec commit 89b035b

File tree

11 files changed

+134
-53
lines changed

11 files changed

+134
-53
lines changed

src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const require = createRequire(import.meta.url);
66
const packageJson = require("../package.json");
77
import "dotenv/config";
88
import logger from "./logger.js";
9-
import { createMcpServer } from "./server-factory.js";
9+
import { BrowserStackMcpServer } from "./server-factory.js";
1010

1111
async function main() {
1212
logger.info(
@@ -33,12 +33,12 @@ async function main() {
3333

3434
const transport = new StdioServerTransport();
3535

36-
const server = createMcpServer({
36+
const mcpServer = new BrowserStackMcpServer({
3737
"browserstack-username": username,
3838
"browserstack-access-key": accessKey,
3939
});
4040

41-
await server.connect(transport);
41+
await mcpServer.getInstance().connect(transport);
4242
}
4343

4444
main().catch(console.error);
@@ -48,5 +48,6 @@ process.on("exit", () => {
4848
logger.flush();
4949
});
5050

51-
export { createMcpServer } from "./server-factory.js";
51+
5252
export { setLogger } from "./logger.js";
53+
export { BrowserStackMcpServer } from "./server-factory.js";

src/server-factory.ts

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1+
import {
2+
McpServer,
3+
RegisteredTool,
4+
} from "@modelcontextprotocol/sdk/server/mcp.js";
25
import { createRequire } from "module";
36
const require = createRequire(import.meta.url);
47
const packageJson = require("../package.json");
@@ -15,32 +18,70 @@ import addAppLiveTools from "./tools/applive.js";
1518
import { setupOnInitialized } from "./oninitialized.js";
1619
import { BrowserStackConfig } from "./lib/types.js";
1720

18-
function registerTools(server: McpServer, config: BrowserStackConfig) {
19-
addAccessibilityTools(server, config);
20-
addSDKTools(server, config);
21-
addAppLiveTools(server, config);
22-
addBrowserLiveTools(server, config);
23-
addTestManagementTools(server, config);
24-
addAppAutomationTools(server, config);
25-
addFailureLogsTools(server, config);
26-
addAutomateTools(server, config);
27-
addSelfHealTools(server, config);
28-
}
21+
/**
22+
* Wrapper class for BrowserStack MCP Server
23+
* Stores a map of registered tools by name
24+
*/
25+
export class BrowserStackMcpServer {
26+
public server: McpServer;
27+
public tools: Record<string, RegisteredTool> = {};
28+
29+
constructor(private config: BrowserStackConfig) {
30+
logger.info(
31+
"Creating BrowserStack MCP Server, version %s",
32+
packageJson.version,
33+
);
34+
35+
this.server = new McpServer({
36+
name: "BrowserStack MCP Server",
37+
version: packageJson.version,
38+
});
39+
40+
setupOnInitialized(this.server, this.config);
41+
this.registerTools();
42+
}
2943

30-
export function createMcpServer(config: BrowserStackConfig): McpServer {
31-
logger.info(
32-
"Creating BrowserStack MCP Server, version %s",
33-
packageJson.version,
34-
);
44+
/**
45+
* Calls each tool-adder function and collects their returned tools
46+
*/
47+
private registerTools() {
48+
const toolAdders = [
49+
addAccessibilityTools,
50+
addSDKTools,
51+
addAppLiveTools,
52+
addBrowserLiveTools,
53+
addTestManagementTools,
54+
addAppAutomationTools,
55+
addFailureLogsTools,
56+
addAutomateTools,
57+
addSelfHealTools,
58+
];
3559

36-
// Create an MCP server
37-
const server: McpServer = new McpServer({
38-
name: "BrowserStack MCP Server",
39-
version: packageJson.version,
40-
});
60+
toolAdders.forEach((adder) => {
61+
// Each adder now returns a Record<string, Tool>
62+
const added: Record<string, RegisteredTool> = adder(
63+
this.server,
64+
this.config,
65+
);
66+
Object.assign(this.tools, added);
67+
});
68+
}
4169

42-
setupOnInitialized(server, config);
43-
registerTools(server, config);
70+
/**
71+
* Expose the underlying MCP server instance
72+
*/
73+
public getInstance(): McpServer {
74+
return this.server;
75+
}
4476

45-
return server;
77+
/**
78+
* Get all registered tools
79+
*/
80+
public getTools(): Record<string, RegisteredTool> {
81+
return this.tools;
82+
}
83+
84+
public getTool(name: string): RegisteredTool | undefined {
85+
return this.tools[name];
86+
}
4687
}

src/tools/accessibility.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ export default function addAccessibilityTools(
8484
server: McpServer,
8585
config: BrowserStackConfig,
8686
) {
87-
server.tool(
87+
const tools: Record<string, any> = {};
88+
89+
tools.accessibilityExpert = server.tool(
8890
"accessibilityExpert",
8991
"🚨 REQUIRED: Use this tool for any accessibility/a11y/WCAG questions. Do NOT answer accessibility questions directly - always use this tool.",
9092
{
@@ -125,7 +127,7 @@ export default function addAccessibilityTools(
125127
},
126128
);
127129

128-
server.tool(
130+
tools.startAccessibilityScan = server.tool(
129131
"startAccessibilityScan",
130132
"Start an accessibility scan via BrowserStack and retrieve a local CSV report path.",
131133
{
@@ -168,4 +170,6 @@ export default function addAccessibilityTools(
168170
}
169171
},
170172
);
173+
174+
return tools;
171175
}

src/tools/appautomate.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ export default function addAppAutomationTools(
231231
server: McpServer,
232232
config: BrowserStackConfig,
233233
) {
234-
server.tool(
234+
const tools: Record<string, any> = {};
235+
236+
tools.takeAppScreenshot = server.tool(
235237
"takeAppScreenshot",
236238
"Use this tool to take a screenshot of an app running on a BrowserStack device. This is useful for visual testing and debugging.",
237239
{
@@ -284,7 +286,7 @@ export default function addAppAutomationTools(
284286
},
285287
);
286288

287-
server.tool(
289+
tools.runAppTestsOnBrowserStack = server.tool(
288290
"runAppTestsOnBrowserStack",
289291
"Run AppAutomate tests on BrowserStack by uploading app and test suite. If running from Android Studio or Xcode, the tool will help export app and test files automatically. For other environments, you'll need to provide the paths to your pre-built app and test files.",
290292
{
@@ -358,4 +360,6 @@ export default function addAppAutomationTools(
358360
}
359361
},
360362
);
363+
364+
return tools;
361365
}

src/tools/applive.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ export default function addAppLiveTools(
7474
server: McpServer,
7575
config: BrowserStackConfig,
7676
) {
77-
server.tool(
77+
const tools: Record<string, any> = {};
78+
79+
tools.runAppLiveSession = server.tool(
7880
"runAppLiveSession",
7981
"Use this tool when user wants to manually check their app on a particular mobile device using BrowserStack's cloud infrastructure. Can be used to debug crashes, slow performance, etc.",
8082
{
@@ -129,4 +131,6 @@ export default function addAppLiveTools(
129131
}
130132
},
131133
);
134+
135+
return tools;
132136
}

src/tools/automate.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ export default function addAutomationTools(
6262
server: McpServer,
6363
config: BrowserStackConfig,
6464
) {
65-
server.tool(
65+
const tools: Record<string, any> = {};
66+
67+
tools.fetchAutomationScreenshots = server.tool(
6668
"fetchAutomationScreenshots",
6769
"Fetch and process screenshots from a BrowserStack Automate session",
6870
{
@@ -102,4 +104,6 @@ export default function addAutomationTools(
102104
}
103105
},
104106
);
107+
108+
return tools;
105109
}

src/tools/bstack-sdk.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ export default function addSDKTools(
167167
server: McpServer,
168168
config: BrowserStackConfig,
169169
) {
170-
server.tool(
170+
const tools: Record<string, any> = {};
171+
172+
tools.runTestsOnBrowserStack = server.tool(
171173
"runTestsOnBrowserStack",
172174
"Use this tool to get instructions for running tests on BrowserStack and BrowserStack Percy. It sets up the BrowserStack SDK and runs your test cases on BrowserStack.",
173175
{
@@ -247,4 +249,6 @@ export default function addSDKTools(
247249
}
248250
},
249251
);
252+
253+
return tools;
250254
}

src/tools/getFailureLogs.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
import { z } from "zod";
33
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4-
import logger from "../logger.js";
54
import { trackMCP } from "../lib/instrumentation.js";
65
import { BrowserStackConfig } from "../lib/types.js";
76

@@ -169,7 +168,9 @@ export default function registerGetFailureLogs(
169168
server: McpServer,
170169
config: BrowserStackConfig,
171170
) {
172-
server.tool(
171+
const tools: Record<string, any> = {};
172+
173+
tools.getFailureLogs = server.tool(
173174
"getFailureLogs",
174175
"Fetch various types of logs from a BrowserStack session. Supports both automate and app-automate sessions.",
175176
{
@@ -212,19 +213,19 @@ export default function registerGetFailureLogs(
212213
);
213214
return await getFailureLogs(args, config);
214215
} catch (error) {
215-
const message = error instanceof Error ? error.message : String(error);
216216
trackMCP(
217217
"getFailureLogs",
218218
server.server.getClientVersion()!,
219219
error,
220220
config,
221221
);
222-
logger.error("Failed to fetch logs: %s", message);
223222
return {
224223
content: [
225224
{
226225
type: "text",
227-
text: `Failed to fetch logs: ${message}`,
226+
text: `Failed to fetch failure logs: ${
227+
error instanceof Error ? error.message : "Unknown error"
228+
}`,
228229
isError: true,
229230
},
230231
],
@@ -233,4 +234,6 @@ export default function registerGetFailureLogs(
233234
}
234235
},
235236
);
237+
238+
return tools;
236239
}

src/tools/live.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ export default function addBrowserLiveTools(
111111
server: McpServer,
112112
config: BrowserStackConfig,
113113
) {
114-
server.tool(
114+
const tools: Record<string, any> = {};
115+
116+
tools.runBrowserLiveSession = server.tool(
115117
"runBrowserLiveSession",
116118
"Launch a BrowserStack Live session (desktop or mobile).",
117119
LiveArgsShape,
@@ -145,4 +147,6 @@ export default function addBrowserLiveTools(
145147
}
146148
},
147149
);
150+
151+
return tools;
148152
}

src/tools/selfheal.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ export default function addSelfHealTools(
3434
server: McpServer,
3535
config: BrowserStackConfig,
3636
) {
37-
server.tool(
37+
const tools: Record<string, any> = {};
38+
39+
tools.fetchSelfHealedSelectors = server.tool(
3840
"fetchSelfHealedSelectors",
3941
"Retrieves AI-generated, self-healed selectors for a BrowserStack Automate session to resolve flaky tests caused by dynamic DOM changes.",
4042
{
@@ -69,4 +71,6 @@ export default function addSelfHealTools(
6971
}
7072
},
7173
);
74+
75+
return tools;
7276
}

0 commit comments

Comments
 (0)