UNPKG

sonatype-mcp

Version:

Model Context Protocol server for Sonatype Nexus Repository Manager

134 lines (133 loc) 4.94 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { createConfig } from './config/environment.js'; import { NexusClient } from './services/nexus-client.js'; import { createTools, getToolByName } from './tools/index.js'; import { formatMCPError } from './utils/errors.js'; /** * Main MCP server for Nexus Repository Manager */ class NexusMCPServer { server; nexusClient = null; tools = []; config = null; constructor() { // Initialize server with default values, config will be loaded later this.server = new Server({ name: 'mcp-sonatype', version: '1.0.3', }, { capabilities: { tools: {}, }, }); } initializeWithConfig() { // Load configuration this.config = createConfig(); // Initialize Nexus client this.nexusClient = new NexusClient(this.config); this.tools = createTools(this.nexusClient, this.config); this.setupHandlers(); } setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: this.tools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, })), }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const tool = getToolByName(this.tools, name); if (!tool) { throw new Error(`Tool not found: ${name}`); } try { console.error(`Executing tool: ${name}`); const result = await tool.handler(args || {}); console.error(`Tool execution completed: ${name}`); return result; } catch (error) { console.error(`Tool execution failed: ${name}`, error); const mcpError = formatMCPError(error); return { content: [ { type: 'text', text: `Error executing ${name}: ${mcpError.message}` } ], isError: true }; } }); } async start() { try { console.error('Starting Nexus MCP Server...'); // Initialize configuration and components this.initializeWithConfig(); if (!this.config || !this.nexusClient) { throw new Error('Failed to initialize server configuration'); } console.error(`Server: ${this.config.server.name} v${this.config.server.version}`); console.error(`Nexus URL: ${this.config.nexus.baseUrl}`); console.error(`Read-only mode: ${this.config.server.readOnly}`); console.error(`Available tools: ${this.tools.length}`); // Test connection to Nexus console.error('Testing connection to Nexus...'); const isConnected = await this.nexusClient.testConnection(); if (!isConnected) { console.warn('Warning: Could not connect to Nexus server'); } else { console.error('Successfully connected to Nexus'); } // Start the server const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Nexus MCP Server started successfully'); } catch (error) { console.error('Failed to start server:', error); process.exit(1); } } async stop() { try { console.error('Stopping Nexus MCP Server...'); await this.server.close(); console.error('Server stopped'); } catch (error) { console.error('Error stopping server:', error); } } } // Handle process signals process.on('SIGINT', async () => { console.error('\nReceived SIGINT, shutting down gracefully...'); process.exit(0); }); process.on('SIGTERM', async () => { console.error('\nReceived SIGTERM, shutting down gracefully...'); process.exit(0); }); // Start the server if this file is run directly if (import.meta.url === `file://${process.argv[1]}`) { const server = new NexusMCPServer(); server.start().catch((error) => { console.error('Failed to start server:', error); process.exit(1); }); }