index.tsโข5.29 kB
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import { browserManager } from "./browser.js";
// Initialize server
const server = new Server(
{
name: "qa-agent-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Tool definitions
const TOOLS = [
{
name: "navigate",
description: "Navigate to a specific URL in the browser",
inputSchema: {
type: "object",
properties: {
url: { type: "string", description: "The URL to navigate to" },
},
required: ["url"],
},
},
{
name: "click",
description: "Click an element on the page identified by a CSS selector",
inputSchema: {
type: "object",
properties: {
selector: { type: "string", description: "CSS selector of the element to click" },
},
required: ["selector"],
},
},
{
name: "type",
description: "Type text into an input field identified by a CSS selector",
inputSchema: {
type: "object",
properties: {
selector: { type: "string", description: "CSS selector of the input field" },
text: { type: "string", description: "Text to type" },
},
required: ["selector", "text"],
},
},
{
name: "get_text",
description: "Get the text content of an element",
inputSchema: {
type: "object",
properties: {
selector: { type: "string", description: "CSS selector of the element" },
},
required: ["selector"],
},
},
{
name: "screenshot",
description: "Take a screenshot of the current page",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "Name for the screenshot file (without extension)" },
},
required: ["name"],
},
},
{
name: "set_viewport",
description: "Set the browser viewport size (e.g., for mobile simulation)",
inputSchema: {
type: "object",
properties: {
width: { type: "number", description: "Viewport width in pixels" },
height: { type: "number", description: "Viewport height in pixels" },
mobile: { type: "boolean", description: "Whether to simulate a mobile device" },
},
required: ["width", "height"],
},
},
{
name: "get_console_logs",
description: "Get all console logs captured during the session",
inputSchema: {
type: "object",
properties: {},
},
},
];
// List tools handler
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: TOOLS,
};
});
// Call tool handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
let result = "";
switch (name) {
case "navigate":
result = await browserManager.navigate(String(args?.url));
break;
case "click":
result = await browserManager.click(String(args?.selector));
break;
case "type":
result = await browserManager.type(String(args?.selector), String(args?.text));
break;
case "get_text":
result = await browserManager.getText(String(args?.selector));
break;
case "screenshot":
result = await browserManager.screenshot(String(args?.name));
break;
case "set_viewport":
result = await browserManager.setViewport(
Number(args?.width),
Number(args?.height),
Boolean(args?.mobile)
);
break;
case "get_console_logs":
result = await browserManager.getConsoleLogs();
break;
default:
throw new Error(`Tool not found: ${name}`);
}
return {
content: [
{
type: "text",
text: result,
},
],
};
} catch (error: any) {
return {
content: [
{
type: "text",
text: `Error: ${error.message}`,
},
],
isError: true,
};
}
});
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("QA Agent MCP Server running on stdio");
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});