@thotischner/observability-mcp 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +41 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -57,38 +57,45 @@ async function main() {
57
57
  const registry = new ConnectorRegistry();
58
58
  await registry.initialize(config);
59
59
  applyConfigToRuntime(config, registry);
60
- const mcpServer = new McpServer({
61
- name: "observability-mcp",
62
- version: "1.0.0",
63
- });
64
- // --- Register tools with Zod schemas ---
65
- mcpServer.tool("list_sources", "List all configured observability backends and their connection status. Use this to discover what data sources are available.", {}, async () => listSourcesHandler(registry));
66
- mcpServer.tool("list_services", "List all monitored services discovered across all connected backends. Returns service names, their data sources, and signal types (metrics/logs).", { filter: z.string().optional().describe("Optional filter to match service names") }, async (args) => listServicesHandler(registry, args));
67
- const metricsList = getAvailableMetricNames(registry);
68
- const metricNames = registry.getBySignal("metrics").flatMap(c => c.getMetrics().map(m => m.name));
69
- const uniqueNames = [...new Set(metricNames)];
70
- mcpServer.tool("query_metrics", `Query a specific metric for a service over a given timeframe. Returns time-series data with pre-computed summary statistics (current, average, min, max, trend). Available metrics: ${metricsList}`, {
71
- service: z.string().describe("Service name (e.g. 'api-gateway', 'payment-service')"),
72
- metric: z.string().describe(`Metric name. Available: ${uniqueNames.join(", ")}`),
73
- duration: z.string().optional().describe("Time range (e.g. '5m', '1h', '24h'). Default: '5m'"),
74
- source: z.string().optional().describe("Specific source name. If omitted, queries all metrics backends."),
75
- groupBy: z.string().optional().describe("Label to break the result down by, e.g. 'instance', 'pod', 'node'. Returns one series per distinct value in 'groups'."),
76
- }, async (args) => queryMetricsHandler(registry, args));
77
- mcpServer.tool("query_logs", "Query logs for a service over a given timeframe. Returns log entries with a summary including error/warning counts and top error patterns.", {
78
- service: z.string().describe("Service name (e.g. 'payment-service')"),
79
- query: z.string().optional().describe("Optional search query to filter log messages (regex supported)"),
80
- duration: z.string().optional().describe("Time range (e.g. '5m', '1h', '24h'). Default: '5m'"),
81
- level: z.string().optional().describe("Filter by log level: 'error', 'warn', 'info', 'debug'"),
82
- limit: z.number().optional().describe("Maximum log entries to return. Default: 100"),
83
- }, async (args) => queryLogsHandler(registry, args));
84
- mcpServer.tool("get_service_health", "Get an aggregated health overview for a service combining metrics AND logs. Returns health score (0-100), status (healthy/degraded/critical), key metrics, log error summary, anomalies, and cross-signal correlations.", {
85
- service: z.string().describe("Service name to check health for"),
86
- }, async (args) => getServiceHealthHandler(registry, args));
87
- mcpServer.tool("detect_anomalies", "Scan for anomalies across all monitored services (or a specific one). Uses z-score analysis on metrics, checks log error spikes, and correlates signals. Returns anomalies with severity ratings.", {
88
- service: z.string().optional().describe("Specific service to scan. If omitted, scans all."),
89
- duration: z.string().optional().describe("Time range to analyze (e.g. '5m', '15m', '1h'). Default: '10m'"),
90
- sensitivity: z.enum(["low", "medium", "high"]).optional().describe("Detection sensitivity: low (>3σ), medium (>2σ), high (>1.5σ). Default: 'medium'"),
91
- }, async (args) => detectAnomaliesHandler(registry, args));
60
+ // The MCP SDK Protocol class permits exactly one transport per instance,
61
+ // so we cannot share a single McpServer across HTTP sessions. Each new
62
+ // session needs its own server. The factory captures the live registry
63
+ // by reference so tool handlers always see the current configuration.
64
+ function createMcpServer() {
65
+ const mcpServer = new McpServer({
66
+ name: "observability-mcp",
67
+ version: "1.3.0",
68
+ });
69
+ // --- Register tools with Zod schemas ---
70
+ mcpServer.tool("list_sources", "List all configured observability backends and their connection status. Use this to discover what data sources are available.", {}, async () => listSourcesHandler(registry));
71
+ mcpServer.tool("list_services", "List all monitored services discovered across all connected backends. Returns service names, their data sources, and signal types (metrics/logs).", { filter: z.string().optional().describe("Optional filter to match service names") }, async (args) => listServicesHandler(registry, args));
72
+ const metricsList = getAvailableMetricNames(registry);
73
+ const metricNames = registry.getBySignal("metrics").flatMap(c => c.getMetrics().map(m => m.name));
74
+ const uniqueNames = [...new Set(metricNames)];
75
+ mcpServer.tool("query_metrics", `Query a specific metric for a service over a given timeframe. Returns time-series data with pre-computed summary statistics (current, average, min, max, trend). Available metrics: ${metricsList}`, {
76
+ service: z.string().describe("Service name (e.g. 'api-gateway', 'payment-service')"),
77
+ metric: z.string().describe(`Metric name. Available: ${uniqueNames.join(", ")}`),
78
+ duration: z.string().optional().describe("Time range (e.g. '5m', '1h', '24h'). Default: '5m'"),
79
+ source: z.string().optional().describe("Specific source name. If omitted, queries all metrics backends."),
80
+ groupBy: z.string().optional().describe("Label to break the result down by, e.g. 'instance', 'pod', 'node'. Returns one series per distinct value in 'groups'."),
81
+ }, async (args) => queryMetricsHandler(registry, args));
82
+ mcpServer.tool("query_logs", "Query logs for a service over a given timeframe. Returns log entries with a summary including error/warning counts and top error patterns.", {
83
+ service: z.string().describe("Service name (e.g. 'payment-service')"),
84
+ query: z.string().optional().describe("Optional search query to filter log messages (regex supported)"),
85
+ duration: z.string().optional().describe("Time range (e.g. '5m', '1h', '24h'). Default: '5m'"),
86
+ level: z.string().optional().describe("Filter by log level: 'error', 'warn', 'info', 'debug'"),
87
+ limit: z.number().optional().describe("Maximum log entries to return. Default: 100"),
88
+ }, async (args) => queryLogsHandler(registry, args));
89
+ mcpServer.tool("get_service_health", "Get an aggregated health overview for a service combining metrics AND logs. Returns health score (0-100), status (healthy/degraded/critical), key metrics, log error summary, anomalies, and cross-signal correlations.", {
90
+ service: z.string().describe("Service name to check health for"),
91
+ }, async (args) => getServiceHealthHandler(registry, args));
92
+ mcpServer.tool("detect_anomalies", "Scan for anomalies across all monitored services (or a specific one). Uses z-score analysis on metrics, checks log error spikes, and correlates signals. Returns anomalies with severity ratings.", {
93
+ service: z.string().optional().describe("Specific service to scan. If omitted, scans all."),
94
+ duration: z.string().optional().describe("Time range to analyze (e.g. '5m', '15m', '1h'). Default: '10m'"),
95
+ sensitivity: z.enum(["low", "medium", "high"]).optional().describe("Detection sensitivity: low (>3σ), medium (>2σ), high (>1.5σ). Default: 'medium'"),
96
+ }, async (args) => detectAnomaliesHandler(registry, args));
97
+ return mcpServer;
98
+ }
92
99
  // --- HTTP server ---
93
100
  const app = express();
94
101
  app.use(express.json({ limit: "1mb" }));
@@ -379,7 +386,8 @@ async function main() {
379
386
  }
380
387
  }
381
388
  };
382
- await mcpServer.connect(transport);
389
+ const sessionMcpServer = createMcpServer();
390
+ await sessionMcpServer.connect(transport);
383
391
  }
384
392
  await transport.handleRequest(req, res, req.body);
385
393
  // Store session after handling (sessionId is set during handleRequest)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thotischner/observability-mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Unified observability gateway for AI agents — one MCP server for Prometheus, Loki, and any backend",
5
5
  "type": "module",
6
6
  "license": "MIT",