Skip to main content
Glama

octomind-mcp

Official
by OctoMind-dev
resources.ts7.82 kB
import { McpServer, ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js"; import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; import { Variables } from "@modelcontextprotocol/sdk/shared/uriTemplate.js"; import { ListResourcesResult, ReadResourceResult, ServerNotification, ServerRequest, } from "@modelcontextprotocol/sdk/types.js"; import { getNotifications, getTestCases, getTestReport, getTestReports, } from "./api"; import { logger } from "./logger"; import { getAllSessions, getSession, Session, setSession } from "./session"; import { TestCaseListItem, TestReport } from "./types"; const validatedSession = async ( extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<Session> => { if (!extra.sessionId) { throw new Error(`No sessionId provided in ${extra}`); } return await getSession(extra.sessionId); }; export const reloadTestReports = async ( session: Session, server: McpServer, ) => { if (!session.currentTestTargetId) { logger.warn( `No test target id found for session ${session.sessionId}, cannot load test reports`, ); session.lastTestReportRefreshTime = Date.now(); await setSession(session); return; } const result = await getTestReports({ sessionId: session.sessionId, testTargetId: session.currentTestTargetId, }); logger.info("Reloaded reports for test target:", session.currentTestTargetId); const reports = result.data; session.testReportIds = []; session.tracesForTestReport = {}; reports.forEach((r: TestReport) => { session.testReportIds.push(r.id); const testResults = r.testResults; for (const testResult of testResults) { if (testResult.traceUrl) { session.tracesForTestReport[r.id] = testResult.traceUrl; } } }); await server.server.notification({ method: "notifications/resources/list_changed", }); session.lastTestReportRefreshTime = Date.now(); await setSession(session); }; export const clearTestReports = async (session: Session, server: McpServer) => { session.testReportIds = []; session.tracesForTestReport = {}; await server.server.notification({ method: "notifications/resources/list_changed", }); session.lastTestReportRefreshTime = Date.now(); await setSession(session); }; export const reloadTestCases = async (session: Session, server: McpServer) => { if (!session.currentTestTargetId) { logger.warn( `No test target id found for session ${session.sessionId}, cannot load test cases`, ); session.lastTestCaseRefreshTime = Date.now(); await setSession(session); return; } const result = await getTestCases({ sessionId: session.sessionId, testTargetId: session.currentTestTargetId, }); session.testCaseIds = result.map((tc: TestCaseListItem) => tc.id); await server.server.notification({ method: "notifications/resources/list_changed", }); session.lastTestCaseRefreshTime = Date.now(); await setSession(session); }; export const checkNotifications = async (server: McpServer): Promise<void> => { for (const session of await getAllSessions()) { if (!session.currentTestTargetId) { continue; } logger.debug( "Checking notifications for test target: %s, session: %s", session.currentTestTargetId, session.sessionId, ); try { await checkNotificationsForSession(server, session); } catch (e) { logger.error( "Failed to check notifications for test target: %s, session: %s", session.currentTestTargetId, session.sessionId, e, ); await setSession({ ...session, currentTestTargetId: undefined }); } } }; const checkNotificationsForSession = async ( server: McpServer, session: Session, ): Promise<void> => { let forceReloadReports = false; let forceReloadTestCases = false; if (session.currentTestTargetId) { logger.info( "Checking notifications for test target:", session.currentTestTargetId, ); const notifications = await getNotifications({ sessionId: session.sessionId, testTargetId: session.currentTestTargetId, }); notifications.forEach(async (n) => { if ( n.type === "REPORT_EXECUTION_FINISHED" && n.updatedAt.getTime() > (session.lastTestReportRefreshTime ?? Date.now()) ) { forceReloadReports = true; } if ( n.type === "DISCOVERY_FINISHED" && n.updatedAt.getTime() > (session.lastTestCaseRefreshTime ?? Date.now()) ) { forceReloadTestCases = true; } }); if (forceReloadReports) { await reloadTestReports(session, server); } if (forceReloadTestCases) { await reloadTestCases(session, server); } } }; export const listTestReports = async ( extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<ListResourcesResult> => { const session = await validatedSession(extra); return { resources: session.testReportIds?.map((reportId) => ({ uri: `testreport://${reportId}`, name: `report: ${reportId}`, mimeType: "application/json", })) ?? [], }; }; export const readTestReport = async ( uri: URL, vars: Variables, extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<ReadResourceResult> => { const session = await validatedSession(extra); if (!session.currentTestTargetId) { throw new Error( `No currentTestTargetId found for session ${session.sessionId}`, ); } logger.info("Reading test report:", uri, vars); const reportId = vars.id as string; const result = await getTestReport({ sessionId: session.sessionId, testTargetId: session.currentTestTargetId, reportId, }); if (result) { return { contents: [ { uri: uri.toString(), mimeType: "application/json", name: `report: ${reportId}`, text: JSON.stringify(result), }, ], }; } else { return { contents: [], }; } }; const listTestResultTraces = async ( extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<ListResourcesResult> => { const session = await validatedSession(extra); return { resources: Object.entries(session.tracesForTestReport).map( ([id, traceUrl]) => ({ uri: `testresulttrace://${id}`, name: `Trace ${id}`, description: `Trace for test result ${id}`, metadata: { traceUrl }, }), ), }; }; const readTestResultTrace = async ( _uri: URL, vars: Variables, extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<ReadResourceResult> => { const id: string = vars.id as string; const session = await validatedSession(extra); const traceUrl = session.tracesForTestReport[id]; if (!traceUrl) { throw new Error(`No trace found for test result ${id}`); } const response = await fetch(traceUrl); if (!response.ok) { throw new Error( `Failed to fetch trace from ${traceUrl}: ${response.statusText}`, ); } const buffer = await response.arrayBuffer(); const base64Data = Buffer.from(buffer).toString("base64"); return { contents: [ { uri: traceUrl, mimeType: "application/zip", name: "trace", text: base64Data, }, ], }; }; export const registerResources = (server: McpServer): void => { server.resource( "test reports", new ResourceTemplate("testreport://{id}", { list: listTestReports, }), readTestReport, ); server.resource( "test result traces", new ResourceTemplate("testresulttrace://{id}", { list: listTestResultTraces, }), readTestResultTrace, ); };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/OctoMind-dev/octomind-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server