UNPKG

@quorum-us/opsgenie-mcp

Version:

MCP server for Opsgenie alert management with comprehensive filtering, custom queries, and AI-friendly interface

115 lines (114 loc) 3.95 kB
import axios from "axios"; import { DEFAULTS, ENDPOINTS, ERROR_MESSAGES, validateLimit, validateOffset, validateIdentifier, buildQueryParams, buildSearchQuery, } from './constants.js'; /** * Opsgenie API Client class for handling all Opsgenie operations */ export class OpsgenieClient { client; apiKey; baseUrl; /** * Constructor for OpsgenieClient * @param config - Configuration object containing API key and optional settings */ constructor(config) { this.apiKey = config.apiKey; this.baseUrl = config.baseUrl ?? DEFAULTS.BASE_URL; this.client = this.createHttpClient(config); } /** * Create HTTP client with proper configuration * @param config - Configuration object * @returns Configured axios instance */ createHttpClient(config) { return axios.create({ baseURL: this.baseUrl, timeout: config.timeout ?? DEFAULTS.TIMEOUT, headers: { 'Authorization': `GenieKey ${this.apiKey}`, 'Content-Type': 'application/json', }, }); } /** * Generic method to handle API responses and errors for MCP * @param apiCall - Promise that makes the API call * @returns Promise that resolves to MCP response */ async handleApiCall(apiCall) { try { const response = await apiCall; return { content: [{ type: "text", text: JSON.stringify(response.data) }], }; } catch (error) { const errorMessage = error.response?.data?.message || error.message || ERROR_MESSAGES.UNKNOWN_ERROR; return { isError: true, content: [{ type: "text", text: `Error: ${errorMessage}`, }], structuredContent: {}, }; } } /** * List alerts with comprehensive filtering options * @param filter - Filter options for alerts * @returns Promise that resolves to MCP response */ async listAlerts(filter = {}) { // Build the search query from filter options const searchQuery = buildSearchQuery({ query: filter.query, status: filter.status, priority: filter.priority, message: filter.message, source: filter.source, owner: filter.owner, tags: filter.tags, teams: filter.teams, }); const params = buildQueryParams({ query: searchQuery || undefined, searchIdentifier: filter.searchIdentifier, searchIdentifierType: filter.searchIdentifierType, offset: validateOffset(filter.offset), limit: validateLimit(filter.limit), sort: filter.sort ?? DEFAULTS.ALERT_SORT, order: filter.order ?? DEFAULTS.ALERT_ORDER, }); return this.handleApiCall(this.client.get(ENDPOINTS.ALERTS, { params })); } /** * Get details of a specific alert * @param identifier - Alert identifier (ID or alias) * @returns Promise that resolves to MCP response */ async getAlert(identifier) { validateIdentifier(identifier); return this.handleApiCall(this.client.get(ENDPOINTS.ALERT_BY_ID(identifier))); } } /** * Factory function to create an OpsgenieClient instance * @param apiKey - Opsgenie API key * @param config - Optional additional configuration * @returns OpsgenieClient instance */ export function createOpsgenieClient(apiKey, config = {}) { const finalApiKey = apiKey ?? process.env.OPSGENIE_API_KEY; if (!finalApiKey) { throw new Error(ERROR_MESSAGES.API_KEY_MISSING); } return new OpsgenieClient({ apiKey: finalApiKey, ...config, }); }