UNPKG

azureai-optimizer

Version:

AI-Powered Azure Infrastructure Optimization via Model Context Protocol

173 lines 6.98 kB
/** * MCP Server Implementation * Handles Model Context Protocol communication and tool execution */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { Logger } from '../utils/logger.js'; import { MCPError, ErrorCode } from '../utils/errors.js'; export class MCPServer { server; auth; tools; logger; config; constructor(options) { this.auth = options.auth; this.tools = options.tools; this.config = options.config; this.logger = new Logger('MCPServer'); // Initialize MCP server this.server = new Server({ name: 'azureai-optimizer', version: '1.0.0' }); this.setupHandlers(); } setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { try { const tools = await this.tools.getTools(); return { tools: tools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })) }; } catch (error) { this.logger.error('Failed to list tools:', error); throw new MCPError(ErrorCode.INTERNAL_ERROR, 'Failed to list tools'); } }); // Execute tool this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; this.logger.info(`🔧 Executing tool: ${name}`); this.logger.debug(`📝 Tool arguments:`, args); // Validate authentication const authContext = await this.auth.getAuthContext(); if (!authContext) { throw new MCPError(ErrorCode.UNAUTHORIZED, 'Azure authentication required'); } // Execute the tool const result = await this.tools.executeTool(name, args, authContext); this.logger.info(`✅ Tool ${name} executed successfully`); this.logger.debug(`📊 Tool result:`, result); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } catch (error) { this.logger.error(`❌ Tool execution failed for ${request.params.name}:`, error); if (error instanceof MCPError) { throw error; } throw new MCPError(ErrorCode.INTERNAL_ERROR, `Tool execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); // List available resources this.server.setRequestHandler(ListResourcesRequestSchema, async () => { try { const resources = await this.tools.getResources(); return { resources: resources.map(resource => ({ uri: resource.uri, name: resource.name, description: resource.description, mimeType: resource.mimeType })) }; } catch (error) { this.logger.error('Failed to list resources:', error); throw new MCPError(ErrorCode.INTERNAL_ERROR, 'Failed to list resources'); } }); // Read resource this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => { try { const { uri } = request.params; this.logger.info(`📖 Reading resource: ${uri}`); // Validate authentication const authContext = await this.auth.getAuthContext(); if (!authContext) { throw new MCPError(ErrorCode.UNAUTHORIZED, 'Azure authentication required'); } const resource = await this.tools.readResource(uri, authContext); return { contents: [ { type: 'resource', resource: { uri: resource.uri, mimeType: resource.mimeType, text: resource.content } } ] }; } catch (error) { this.logger.error(`❌ Resource read failed for ${request.params.uri}:`, error); if (error instanceof MCPError) { throw error; } throw new MCPError(ErrorCode.INTERNAL_ERROR, `Resource read failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); // Error handling this.server.onerror = (error) => { this.logger.error('MCP Server error:', error); }; } async start() { try { let transport; switch (this.config.transport) { case 'stdio': transport = new StdioServerTransport(); this.logger.info('🔌 Using STDIO transport'); break; case 'sse': const port = this.config.port || 8080; const host = this.config.host || 'localhost'; transport = new SSEServerTransport(null, null); this.logger.info(`🌐 Using SSE transport on http://${host}:${port}/sse`); break; default: throw new Error(`Unsupported transport: ${this.config.transport}`); } await this.server.connect(transport); this.logger.info('🎯 MCP Server connected and ready'); } catch (error) { this.logger.error('Failed to start MCP server:', error); throw error; } } async stop() { try { await this.server.close(); this.logger.info('🛑 MCP Server stopped'); } catch (error) { this.logger.error('Error stopping MCP server:', error); throw error; } } getServer() { return this.server; } } //# sourceMappingURL=mcp-server.js.map