UNPKG

@smartbear/mcp

Version:

MCP server for interacting SmartBear Products

233 lines (232 loc) 8.76 kB
import { z } from "zod"; import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../common/info.js"; import { ToolError, } from "../common/types.js"; const ConfigurationSchema = z.object({ api_token: z.string().describe("Reflect API authentication token"), }); // ReflectClient class implementing the Client interface export class ReflectClient { headers = {}; name = "Reflect"; toolPrefix = "reflect"; configPrefix = "Reflect"; config = ConfigurationSchema; async configure(_server, config, _cache) { this.headers = { "X-API-KEY": `${config.api_token}`, "Content-Type": "application/json", "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`, }; return true; } async listReflectSuites() { const response = await fetch("https://api.reflect.run/v1/suites", { method: "GET", headers: this.headers, }); return response.json(); } async listSuiteExecutions(suiteId) { const response = await fetch(`https://api.reflect.run/v1/suites/${suiteId}/executions`, { method: "GET", headers: this.headers, }); return response.json(); } async getSuiteExecutionStatus(suiteId, executionId) { const response = await fetch(`https://api.reflect.run/v1/suites/${suiteId}/executions/${executionId}`, { method: "GET", headers: this.headers, }); return response.json(); } async executeSuite(suiteId) { const response = await fetch(`https://api.reflect.run/v1/suites/${suiteId}/executions`, { method: "POST", headers: this.headers, }); return response.json(); } async cancelSuiteExecution(suiteId, executionId) { const response = await fetch(`https://api.reflect.run/v1/suites/${suiteId}/executions/${executionId}/cancel`, { method: "PATCH", headers: this.headers, }); return response.json(); } async listReflectTests() { const response = await fetch("https://api.reflect.run/v1/tests", { method: "GET", headers: this.headers, }); return response.json(); } async runReflectTest(testId) { const response = await fetch(`https://api.reflect.run/v1/tests/${testId}/executions`, { method: "POST", headers: this.headers, }); return response.json(); } async getReflectTestStatus(_testId, executionId) { const response = await fetch(`https://api.reflect.run/v1/executions/${executionId}`, { method: "GET", headers: this.headers, }); return response.json(); } registerTools(register, _getInput) { register({ title: "List Suites", summary: "Retrieve a list of all reflect suites available", parameters: [], }, async (_args, _extra) => { const response = await this.listReflectSuites(); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "List Suite Executions", summary: "List all executions for a given suite", parameters: [ { name: "suiteId", type: z.string(), description: "ID of the reflect suite to list executions for", required: true, }, ], }, async (args, _extra) => { if (!args.suiteId) throw new ToolError("suiteId argument is required"); const response = await this.listSuiteExecutions(args.suiteId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "Get Suite Execution Status", summary: "Get the status of a reflect suite execution", parameters: [ { name: "suiteId", type: z.string(), description: "ID of the reflect suite to get execution status for", required: true, }, { name: "executionId", type: z.string(), description: "ID of the reflect suite execution to get status for", required: true, }, ], }, async (args, _extra) => { if (!args.suiteId || !args.executionId) throw new ToolError("Both suiteId and executionId arguments are required"); const response = await this.getSuiteExecutionStatus(args.suiteId, args.executionId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "Execute Suite", summary: "Execute a reflect suite", parameters: [ { name: "suiteId", type: z.string(), description: "ID of the reflect suite to list executions for", required: true, }, ], }, async (args, _extra) => { if (!args.suiteId) throw new ToolError("suiteId argument is required"); const response = await this.executeSuite(args.suiteId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "Cancel Suite Execution", summary: "Cancel a reflect suite execution", parameters: [ { name: "suiteId", type: z.string(), description: "ID of the reflect suite to cancel execution for", required: true, }, { name: "executionId", type: z.string(), description: "ID of the reflect suite execution to cancel", required: true, }, ], }, async (args, _extra) => { if (!args.suiteId || !args.executionId) throw new ToolError("Both suiteId and executionId arguments are required"); const response = await this.cancelSuiteExecution(args.suiteId, args.executionId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "List Tests", summary: "List all reflect tests", parameters: [], }, async (_args, _extra) => { const response = await this.listReflectTests(); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "Run Test", summary: "Run a reflect test", parameters: [ { name: "testId", type: z.string(), description: "ID of the reflect test to run", required: true, }, ], }, async (args, _extra) => { if (!args.testId) throw new ToolError("testId argument is required"); const response = await this.runReflectTest(args.testId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); register({ title: "Get Test Status", summary: "Get the status of a reflect test execution", parameters: [ { name: "testId", type: z.string(), description: "ID of the reflect test to run", required: true, }, { name: "executionId", type: z.string(), description: "ID of the reflect test execution to get status for", required: true, }, ], }, async (args, _extra) => { if (!args.testId || !args.executionId) throw new ToolError("Both testId and executionId arguments are required"); const response = await this.getReflectTestStatus(args.testId, args.executionId); return { content: [{ type: "text", text: JSON.stringify(response) }], }; }); } }