azureai-optimizer
Version:
AI-Powered Azure Infrastructure Optimization via Model Context Protocol
173 lines • 6.98 kB
JavaScript
/**
* 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