feat: add lab-monitoring MCP server for Prometheus and Alertmanager

New MCP server that queries live Prometheus and Alertmanager HTTP APIs
with 8 tools: list_alerts, get_alert, search_metrics, get_metric_metadata,
query (PromQL), list_targets, list_silences, and create_silence.

Extends the MCP core with ModeCustom and NewGenericServer for servers
that don't require a database. Includes CLI with direct commands
(alerts, query, targets, metrics), NixOS module, and comprehensive
httptest-based tests.

Bumps existing binaries to 0.2.1 due to shared internal/mcp change.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 23:11:53 +01:00
parent 0bd4ed778a
commit 1755364bba
19 changed files with 2567 additions and 22 deletions

View File

@@ -18,6 +18,8 @@ const (
ModeOptions ServerMode = "options"
// ModePackages exposes only package-related tools.
ModePackages ServerMode = "packages"
// ModeCustom exposes externally registered tools (no database required).
ModeCustom ServerMode = "custom"
)
// ServerConfig contains configuration for the MCP server.
@@ -40,7 +42,7 @@ type ServerConfig struct {
func DefaultNixOSConfig() ServerConfig {
return ServerConfig{
Name: "nixos-options",
Version: "0.2.0",
Version: "0.2.1",
DefaultChannel: "nixos-stable",
SourceName: "nixpkgs",
Mode: ModeOptions,
@@ -60,7 +62,7 @@ This ensures option documentation matches the nixpkgs version the project actual
func DefaultNixpkgsPackagesConfig() ServerConfig {
return ServerConfig{
Name: "nixpkgs-packages",
Version: "0.2.0",
Version: "0.2.1",
DefaultChannel: "nixos-stable",
SourceName: "nixpkgs",
Mode: ModePackages,
@@ -74,11 +76,29 @@ This ensures package information matches the nixpkgs version the project actuall
}
}
// DefaultMonitoringConfig returns the default configuration for the lab monitoring server.
func DefaultMonitoringConfig() ServerConfig {
return ServerConfig{
Name: "lab-monitoring",
Version: "0.1.0",
Mode: ModeCustom,
Instructions: `Lab Monitoring MCP Server - Query Prometheus metrics and Alertmanager alerts.
Tools for querying your monitoring stack:
- Search and query Prometheus metrics with PromQL
- List and inspect alerts from Alertmanager
- View scrape target health status
- Manage alert silences
All queries are executed against live Prometheus and Alertmanager HTTP APIs.`,
}
}
// DefaultHomeManagerConfig returns the default configuration for Home Manager options server.
func DefaultHomeManagerConfig() ServerConfig {
return ServerConfig{
Name: "hm-options",
Version: "0.2.0",
Version: "0.2.1",
DefaultChannel: "hm-stable",
SourceName: "home-manager",
Mode: ModeOptions,
@@ -99,6 +119,7 @@ type Server struct {
store database.Store
config ServerConfig
tools map[string]ToolHandler
toolDefs []Tool
initialized bool
logger *log.Logger
}
@@ -106,7 +127,7 @@ type Server struct {
// ToolHandler is a function that handles a tool call.
type ToolHandler func(ctx context.Context, args map[string]interface{}) (CallToolResult, error)
// NewServer creates a new MCP server with the given configuration.
// NewServer creates a new MCP server with a database store.
func NewServer(store database.Store, logger *log.Logger, config ServerConfig) *Server {
if logger == nil {
logger = log.New(io.Discard, "", 0)
@@ -121,6 +142,25 @@ func NewServer(store database.Store, logger *log.Logger, config ServerConfig) *S
return s
}
// NewGenericServer creates a new MCP server without a database store.
// Use RegisterTool to add tools externally.
func NewGenericServer(logger *log.Logger, config ServerConfig) *Server {
if logger == nil {
logger = log.New(io.Discard, "", 0)
}
return &Server{
config: config,
tools: make(map[string]ToolHandler),
logger: logger,
}
}
// RegisterTool registers an externally defined tool with its handler.
func (s *Server) RegisterTool(tool Tool, handler ToolHandler) {
s.toolDefs = append(s.toolDefs, tool)
s.tools[tool.Name] = handler
}
// registerTools registers all available tools.
func (s *Server) registerTools() {
// Tools will be implemented in handlers.go
@@ -237,6 +277,11 @@ func (s *Server) handleToolsList(req *Request) *Response {
// getToolDefinitions returns the tool definitions.
func (s *Server) getToolDefinitions() []Tool {
// For custom mode, return externally registered tools
if s.config.Mode == ModeCustom {
return s.toolDefs
}
// For packages mode, return package tools
if s.config.Mode == ModePackages {
return s.getPackageToolDefinitions()