UNPKG

@access-mcp/compute-resources

Version:

MCP server for ACCESS-CI Compute Resources API

171 lines (170 loc) 6.64 kB
import { BaseAccessServer, handleApiError, sanitizeGroupId, } from "@access-mcp/shared"; export class ComputeResourcesServer extends BaseAccessServer { constructor() { super("access-mcp-compute-resources", "0.3.0", "https://operations-api.access-ci.org"); } getTools() { return [ { name: "list_compute_resources", description: "List all ACCESS-CI compute resources", inputSchema: { type: "object", properties: {}, required: [], }, }, { name: "get_compute_resource", description: "Get detailed information about a specific compute resource", inputSchema: { type: "object", properties: { resource_id: { type: "string", description: "The resource ID or info_groupid", }, }, required: ["resource_id"], }, }, { name: "get_resource_hardware", description: "Get hardware specifications for a compute resource", inputSchema: { type: "object", properties: { resource_id: { type: "string", description: "The resource ID or info_groupid", }, }, required: ["resource_id"], }, }, ]; } getResources() { return [ { uri: "accessci://compute-resources", name: "ACCESS-CI Compute Resources", description: "Information about ACCESS-CI compute resources, hardware, and software", mimeType: "application/json", }, ]; } async handleToolCall(request) { const { name, arguments: args } = request.params; try { switch (name) { case "list_compute_resources": return await this.listComputeResources(); case "get_compute_resource": return await this.getComputeResource(args.resource_id); case "get_resource_hardware": return await this.getResourceHardware(args.resource_id); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `Error: ${handleApiError(error)}`, }, ], }; } } async handleResourceRead(request) { const { uri } = request.params; if (uri === "accessci://compute-resources") { return { contents: [ { uri, mimeType: "text/plain", text: "ACCESS-CI Compute Resources API - Use the available tools to query compute resources, hardware specifications, and software availability.", }, ], }; } throw new Error(`Unknown resource: ${uri}`); } async listComputeResources() { // Get all active resource groups const response = await this.httpClient.get("/wh2/cider/v1/access-active-groups/type/resource-catalog.access-ci.org/"); // Check if the response has the expected structure if (!response.data || !response.data.results || !response.data.results.active_groups) { throw new Error(`Unexpected API response structure. Got: ${JSON.stringify(response.data)}`); } const computeResources = response.data.results.active_groups .filter((group) => { // Filter for compute resources (category 1 = "Compute & Storage Resources") return (group.rollup_info_resourceids && !group.rollup_feature_ids.includes(137)); }) .map((group) => ({ id: group.info_groupid, name: group.group_descriptive_name, description: group.group_description, organization: group.rollup_organization_ids, features: group.rollup_feature_ids, resources: group.rollup_info_resourceids, logoUrl: group.group_logo_url, accessAllocated: group.rollup_feature_ids.includes(139), })); return { content: [ { type: "text", text: JSON.stringify({ total: computeResources.length, resources: computeResources, }, null, 2), }, ], }; } async getComputeResource(resourceId) { const sanitizedId = sanitizeGroupId(resourceId); // Get detailed resource information const response = await this.httpClient.get(`/wh2/cider/v1/access-active/info_groupid/${sanitizedId}/?format=json`); return { content: [ { type: "text", text: JSON.stringify(response.data.results, null, 2), }, ], }; } async getResourceHardware(resourceId) { // For now, return hardware info from the detailed resource endpoint // This could be enhanced with dedicated hardware endpoints if available const resourceData = await this.getComputeResource(resourceId); // Extract hardware-related information const fullData = JSON.parse(resourceData.content[0].text); const hardwareInfo = fullData.filter((item) => item.cider_type === "Compute" || item.cider_type === "Storage" || item.resource_descriptive_name?.toLowerCase().includes("node") || item.resource_descriptive_name?.toLowerCase().includes("core") || item.resource_descriptive_name?.toLowerCase().includes("memory")); return { content: [ { type: "text", text: JSON.stringify({ resource_id: resourceId, hardware: hardwareInfo, }, null, 2), }, ], }; } }