UNPKG

sonatype-mcp

Version:

Model Context Protocol server for Sonatype Nexus Repository Manager

170 lines (169 loc) 5.28 kB
import axios from 'axios'; import { createAuthHeaders, validateCredentials } from '../utils/auth.js'; import { handleNexusError, AuthenticationError, ConfigurationError } from '../utils/errors.js'; /** * Nexus Repository Manager REST API client */ export class NexusClient { client; config; constructor(config) { this.config = config; // Validate configuration if (!validateCredentials(config)) { throw new ConfigurationError('Invalid Nexus credentials: username and password are required'); } // Create axios instance with default configuration this.client = axios.create({ baseURL: config.nexus.baseUrl, timeout: config.nexus.timeout, headers: createAuthHeaders(config), validateStatus: () => true, // We'll handle all status codes manually ...(config.nexus.validateSsl === false && { httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false }) }) }); // Request interceptor for logging this.client.interceptors.request.use((config) => { console.error(`Making request to: ${config.method?.toUpperCase()} ${config.url}`); return config; }, (error) => { console.error('Request interceptor error:', error); return Promise.reject(error); }); // Response interceptor for error handling this.client.interceptors.response.use((response) => { console.error(`Response: ${response.status} ${response.statusText}`); return response; }, (error) => { console.error('Response interceptor error:', error); return Promise.reject(error); }); } /** * Test the connection to Nexus */ async testConnection() { try { const response = await this.client.get('/service/rest/v1/status/check'); return response.status === 200; } catch (error) { console.error('Connection test failed:', error); return false; } } /** * Make a GET request to Nexus API */ async get(endpoint, options = {}) { try { const response = await this.client.get(endpoint, { ...options, headers: { ...createAuthHeaders(this.config), ...options.headers } }); if (response.status >= 400) { throw { response }; } return response.data; } catch (error) { handleNexusError(error); } } /** * Make a POST request to Nexus API */ async post(endpoint, data, options = {}) { if (this.config.server.readOnly) { throw new AuthenticationError('Write operations are disabled in read-only mode'); } try { const response = await this.client.post(endpoint, data, { ...options, headers: { ...createAuthHeaders(this.config), ...options.headers } }); if (response.status >= 400) { throw { response }; } return response.data; } catch (error) { handleNexusError(error); } } /** * Make a PUT request to Nexus API */ async put(endpoint, data, options = {}) { if (this.config.server.readOnly) { throw new AuthenticationError('Write operations are disabled in read-only mode'); } try { const response = await this.client.put(endpoint, data, { ...options, headers: { ...createAuthHeaders(this.config), ...options.headers } }); if (response.status >= 400) { throw { response }; } return response.data; } catch (error) { handleNexusError(error); } } /** * Make a DELETE request to Nexus API */ async delete(endpoint, options = {}) { if (this.config.server.readOnly) { throw new AuthenticationError('Write operations are disabled in read-only mode'); } try { const response = await this.client.delete(endpoint, { ...options, headers: { ...createAuthHeaders(this.config), ...options.headers } }); if (response.status >= 400) { throw { response }; } return response.data; } catch (error) { handleNexusError(error); } } /** * Get server information */ async getServerInfo() { return this.get('/service/rest/v1/status'); } /** * Get read-only mode status */ isReadOnly() { return this.config.server.readOnly; } /** * Get base URL */ getBaseUrl() { return this.config.nexus.baseUrl; } }