7
7
"github.com/grafana/grafana-openapi-client-go/client/provisioning"
8
8
"github.com/grafana/grafana-openapi-client-go/models"
9
9
"github.com/mark3labs/mcp-go/server"
10
-
"github.com/prometheus/prometheus/model/labels"
11
10
12
11
mcpgrafana "github.com/grafana/mcp-grafana"
13
12
)
@@ -35,8 +34,11 @@ func (p ListAlertRulesParams) validate() error {
35
34
}
36
35
37
36
type alertRuleSummary struct {
38
-
UID string `json:"uid"`
39
-
Title string `json:"title"`
37
+
UID string `json:"uid"`
38
+
Title string `json:"title"`
39
+
// State can be one of: pending, firing, error, recovering, inactive.
40
+
// "inactive" means the alert state is normal, not firing.
41
+
State string `json:"state"`
40
42
Labels map[string]string `json:"labels,omitempty"`
41
43
}
42
44
@@ -45,13 +47,21 @@ func listAlertRules(ctx context.Context, args ListAlertRulesParams) ([]alertRule
45
47
return nil, fmt.Errorf("list alert rules: %w", err)
46
48
}
47
49
48
-
c := mcpgrafana.GrafanaClientFromContext(ctx)
49
-
response, err := c.Provisioning.GetAlertRules()
50
+
c, err := newAlertingClientFromContext(ctx)
51
+
if err != nil {
52
+
return nil, fmt.Errorf("list alert rules: %w", err)
53
+
}
54
+
response, err := c.GetRules(ctx)
50
55
if err != nil {
51
56
return nil, fmt.Errorf("list alert rules: %w", err)
52
57
}
53
58
54
-
alertRules, err := filterAlertRules(response.Payload, args.LabelSelectors)
59
+
alertRules := []alertingRule{}
60
+
for _, group := range response.Data.RuleGroups {
61
+
alertRules = append(alertRules, group.Rules...)
62
+
}
63
+
64
+
alertRules, err = filterAlertRules(alertRules, args.LabelSelectors)
55
65
if err != nil {
56
66
return nil, fmt.Errorf("list alert rules: %w", err)
57
67
}
@@ -65,18 +75,14 @@ func listAlertRules(ctx context.Context, args ListAlertRulesParams) ([]alertRule
65
75
}
66
76
67
77
// filterAlertRules filters a list of alert rules based on label selectors
68
-
func filterAlertRules(rules models.ProvisionedAlertRules, selectors []Selector) (models.ProvisionedAlertRules, error) {
78
+
func filterAlertRules(rules []alertingRule, selectors []Selector) ([]alertingRule, error) {
69
79
if len(selectors) == 0 {
70
80
return rules, nil
71
81
}
72
82
73
-
filteredResult := models.ProvisionedAlertRules{}
83
+
filteredResult := []alertingRule{}
74
84
for _, rule := range rules {
75
-
if rule == nil {
76
-
continue
77
-
}
78
-
79
-
match, err := matchesSelectors(*rule, selectors)
85
+
match, err := matchesSelectors(rule, selectors)
80
86
if err != nil {
81
87
return nil, fmt.Errorf("filtering alert rules: %w", err)
82
88
}
@@ -90,11 +96,9 @@ func filterAlertRules(rules models.ProvisionedAlertRules, selectors []Selector)
90
96
}
91
97
92
98
// matchesSelectors checks if an alert rule matches all provided selectors
93
-
func matchesSelectors(rule models.ProvisionedAlertRule, selectors []Selector) (bool, error) {
94
-
promLabels := labels.FromMap(rule.Labels)
95
-
99
+
func matchesSelectors(rule alertingRule, selectors []Selector) (bool, error) {
96
100
for _, selector := range selectors {
97
-
match, err := selector.Matches(promLabels)
101
+
match, err := selector.Matches(rule.Labels)
98
102
if err != nil {
99
103
return false, err
100
104
}
@@ -105,26 +109,22 @@ func matchesSelectors(rule models.ProvisionedAlertRule, selectors []Selector) (b
105
109
return true, nil
106
110
}
107
111
108
-
func summarizeAlertRules(alertRules models.ProvisionedAlertRules) []alertRuleSummary {
112
+
func summarizeAlertRules(alertRules []alertingRule) []alertRuleSummary {
109
113
result := make([]alertRuleSummary, 0, len(alertRules))
110
114
for _, r := range alertRules {
111
-
title := ""
112
-
if r.Title != nil {
113
-
title = *r.Title
114
-
}
115
-
116
115
result = append(result, alertRuleSummary{
117
116
UID: r.UID,
118
-
Title: title,
119
-
Labels: r.Labels,
117
+
Title: r.Name,
118
+
State: r.State,
119
+
Labels: r.Labels.Map(),
120
120
})
121
121
}
122
122
return result
123
123
}
124
124
125
125
// applyPagination applies pagination to the list of alert rules.
126
126
// It doesn't sort the items and relies on the order returned by the API.
127
-
func applyPagination(items models.ProvisionedAlertRules, limit, page int) (models.ProvisionedAlertRules, error) {
127
+
func applyPagination(items []alertingRule, limit, page int) ([]alertingRule, error) {
128
128
if limit == 0 {
129
129
limit = DefaultListAlertRulesLimit
130
130
}
@@ -136,7 +136,7 @@ func applyPagination(items models.ProvisionedAlertRules, limit, page int) (model
136
136
end := start + limit
137
137
138
138
if start >= len(items) {
139
-
return models.ProvisionedAlertRules{}, nil
139
+
return nil, nil
140
140
} else if end > len(items) {
141
141
return items[start:], nil
142
142
}
@@ -146,7 +146,7 @@ func applyPagination(items models.ProvisionedAlertRules, limit, page int) (model
146
146
147
147
var ListAlertRules = mcpgrafana.MustTool(
148
148
"list_alert_rules",
149
-
"List alert rules",
149
+
"Lists alert rules with their current states (pending, firing, error, recovering, inactive) and labels. Inactive state means the alert state is normal, not firing.",
150
150
listAlertRules,
151
151
)
152
152
@@ -177,7 +177,7 @@ func getAlertRuleByUID(ctx context.Context, args GetAlertRuleByUIDParams) (*mode
177
177
178
178
var GetAlertRuleByUID = mcpgrafana.MustTool(
179
179
"get_alert_rule_by_uid",
180
-
"Get alert rule by uid",
180
+
"Retrieves detailed information about a specific alert rule by its UID.",
181
181
getAlertRuleByUID,
182
182
)
183
183
@@ -250,7 +250,7 @@ func applyLimitToContactPoints(items []*models.EmbeddedContactPoint, limit int)
250
250
251
251
var ListContactPoints = mcpgrafana.MustTool(
252
252
"list_contact_points",
253
-
"List contact points",
253
+
"Lists notification contact points with their type, name, and configuration.",
254
254
listContactPoints,
255
255
)
256
256
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4