Skip to content

Commit f425f87

Browse files
committed
feat(tools): add tool to get label_names
Signed-off-by: TJ Hoplock <[email protected]>
1 parent 5b363de commit f425f87

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

pkg/mcp/promapi.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,25 @@ func seriesApiCall(ctx context.Context, matchers []string, start, end time.Time)
168168
return string(jsonBytes), nil
169169
}
170170

171+
func labelNamesApiCall(ctx context.Context, matchers []string, start, end time.Time) (string, error) {
172+
result, warnings, err := apiV1Client.LabelNames(ctx, matchers, start, end)
173+
if err != nil {
174+
return "", fmt.Errorf("error getting label names: %w", err)
175+
}
176+
177+
res := queryApiResponse{
178+
Result: strings.Join(result, "\n"),
179+
Warnings: warnings,
180+
}
181+
182+
jsonBytes, err := json.Marshal(res)
183+
if err != nil {
184+
return "", fmt.Errorf("error converting label names response to JSON: %w", err)
185+
}
186+
187+
return string(jsonBytes), nil
188+
}
189+
171190
func buildinfoApiCall(ctx context.Context) (string, error) {
172191
ctx, cancel := context.WithTimeout(ctx, apiTimeout)
173192
defer cancel()

pkg/mcp/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func NewServer(logger *slog.Logger) *server.MCPServer {
2828
mcpServer.AddTool(queryTool, queryToolHandler)
2929
mcpServer.AddTool(rangeQueryTool, rangeQueryToolHandler)
3030
mcpServer.AddTool(seriesTool, seriesToolHandler)
31+
mcpServer.AddTool(labelNamesTool, labelNamesToolHandler)
3132
mcpServer.AddTool(tsdbStatsTool, tsdbStatsToolHandler)
3233
mcpServer.AddTool(listAlertsTool, listAlertsToolHandler)
3334
mcpServer.AddTool(alertmanagersTool, alertmanagersToolHandler)

pkg/mcp/tools.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ var (
6161
mcp.Description("[Optional] End timestamp for the query to be executed at."+
6262
" Must be either Unix timestamp or RFC3339. Defaults to current time."),
6363
),
64+
)
65+
66+
labelNamesTool = mcp.NewTool("label_names",
67+
mcp.WithDescription("Returns the unique label names present in the block in sorted order by given time range and matchers"),
68+
mcp.WithArray("matchers",
69+
mcp.Required(),
70+
mcp.Description("Label matchers"),
71+
),
72+
mcp.WithString("start_time",
73+
mcp.Description("[Optional] Start timestamp for the query to be executed at."+
74+
" Must be either Unix timestamp or RFC3339. Defaults to 5m ago."),
75+
),
76+
mcp.WithString("end_time",
77+
mcp.Required(),
78+
mcp.Description("[Optional] End timestamp for the query to be executed at."+
79+
" Must be either Unix timestamp or RFC3339. Defaults to current time."),
6480
),
6581
)
6682

@@ -208,6 +224,43 @@ func seriesToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.C
208224
return mcp.NewToolResultText(data), err
209225
}
210226

227+
func labelNamesToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
228+
arguments := request.Params.Arguments
229+
argMatchers, ok := arguments["matchers"].([]any)
230+
if !ok {
231+
return nil, errors.New("matchers must be an array")
232+
}
233+
234+
matchers := make([]string, len(argMatchers))
235+
for i, m := range argMatchers {
236+
matchers[i] = m.(string)
237+
}
238+
239+
endTs := time.Now()
240+
startTs := endTs.Add(DefaultLookbackDelta)
241+
242+
if argEndTime, ok := arguments["end_time"].(string); ok {
243+
parsedEndTime, err := mcpProm.ParseTimestamp(argEndTime)
244+
if err != nil {
245+
return nil, fmt.Errorf("failed to parse end_time %s from args: %w", argEndTime, err)
246+
}
247+
248+
endTs = parsedEndTime
249+
}
250+
251+
if argStartTime, ok := arguments["start_time"].(string); ok {
252+
parsedStartTime, err := mcpProm.ParseTimestamp(argStartTime)
253+
if err != nil {
254+
return nil, fmt.Errorf("failed to parse start_time %s from args: %w", argStartTime, err)
255+
}
256+
257+
startTs = parsedStartTime
258+
}
259+
260+
data, err := labelNamesApiCall(ctx, matchers, startTs, endTs)
261+
return mcp.NewToolResultText(data), err
262+
}
263+
211264
func listAlertsToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
212265
data, err := listAlertsApiCall(ctx)
213266
return mcp.NewToolResultText(data), err

0 commit comments

Comments
 (0)